dart, reflection symbols from strings - reflection

When you deploy a dart app so the code is minified, will the following code still work? as I read that strings are maintained but all symbols are minified, so how will the symbol in the invoke method call be created properly if the method name is minified but the string is left as 'sayHi'?
import 'dart:mirrors';
void main() {
var inst = new MyClass(33);
var instMirror = reflect(inst);
var res = instMirror.invoke(new Symbol('sayHi'), []).reflectee;
}
class MyClass{
int x;
MyClass(this.x);
int sayHi(){
print('this class has x = $x');
return x;
}
}

You can write the symbol as a constant as either const Symbol('sayHi') or the shorter #sayHi. That will be minified to match the minified method name. It's possible that new Symbol() with a constant argument might also get minified. Obviously new Symbol with a dynamic argument won't.

Related

dart, how to get the symbol for a specific member?

What is the most efficient way of getting the symbol for a single member of a class?
import 'dart:mirrors';
class TestClass{
void iWantThisSymbol(){}
void butNotThisOne(){}
}
/**
* I can get all the symbols and filter down but this isn't nice
*/
void main(){
var allSymbols = reflectClass(TestClass).instanceMembers.keys;
var justTheSymbolIWant = allSymbols.where((symbol) => symbol.toString().contains('iWantThisSymbol')); // this doesnt seem very efficient or maintainable
}
var justTheSymbolIWant = reflectClass(TestClass).instanceMembers[#iWantThisSymbol]
Although, to be a bit pedantic, you're not get getting a Symbol, you're using a Symbol (#iWantThisSymbol) to get a member, which in this case is a method. So I would rewrite this as:
import 'dart:mirrors';
class TestClass{
void iWantThisMethod(){}
void butNotThisOne(){}
}
void main(){
var justTheMethodIWant = reflectClass(TestClass).instanceMembers[#iWantThisMethod];
}
Also, a few things about that use of where():
If you do want to filter a list of Symbols, you don't need to them convert to a String, you can just compare symbol instances directly.
.where() returns an iterable, even if there's only one item that matches. You probably want firstWhere() which always returns a single item.
var justTheSymbolIWant = allSymbols.firstWhere((symbol) => symbol == #iWantThisSymbol);

How to parse query strings in Dart?

How do I parse query strings safely in Dart?
Let's assume I have q string with the value of:
?page=main&action=front&sid=h985jg9034gj498g859gh495
Ideally the code should work both in the server and client, but for now I'll settle for a working client-side code.
The simpler, the better. Look for the splitQueryString static method of class Uri.
Map<String, String> splitQueryString(String query, {Encoding encoding: UTF8})
Returns the query split into a map according to the rules specified for
FORM post in the HTML 4.01 specification section 17.13.4. Each key and value
in the returned map has been decoded. If the query is the empty string an
empty map is returned.
I have made a simple package for that purpose exactly: https://github.com/kaisellgren/QueryString
Example:
import 'package:query_string/query_string.dart');
void main() {
var q = '?page=main&action=front&sid=h985jg9034gj498g859gh495&enc=+Hello%20&empty';
var r = QueryString.parse(q);
print(r['page']); // "main"
print(r['asdasd']); // null
}
The result is a Map. Accessing parameters is just a simple r['action'] and accessing a non-existant query parameter is null.
Now, to install, add to your pubspec.yaml as a dependency:
dependencies:
query_string: any
And run pub install.
The library also handles decoding of things like %20 and +, and works even for empty parameters.
It does not support "array style parameters", because they are not part of the RFC 3986 specification.
I done that just like this:
Map<String, String> splitQueryString(String query) {
return query.split("&").fold({}, (map, element) {
int index = element.indexOf("=");
if (index == -1) {
if (element != "") {
map[element] = "";
}
} else if (index != 0) {
var key = element.substring(0, index);
var value = element.substring(index + 1);
map[key] = value;
}
return map;
});
}
I took it from splitQueryString

Save (already-existing) QSetting into an INI file

I want to save an alredy-existing QSettings object into some INI file for backup.
The QSettings comes from the application's global settings, ie. it can be registry, ini file, etc.
In case it helps, my context is:
class Params
{
// All params as data members
// ...
void loadGlobal ()
{
Qettings s; // Global parameters, paths set by application
// Fill data members: s.value (...);
}
};
class Algo
{
Result run (Params p)
{
Result r = F(p);
return r;
}
};
int main (...)
{
Params p;
p.loadGlobal ();
Algo a;
Result r = a.run (p);
// At this point, save Result and Params into a specific directory
// Is there a way to do:
p.saveToIni ("myparams.ini"); // <-- WRONG
}
A solution would be to add a saveTo (QSetting & s) method into the Params class:
class Params
{
void saveTo (QSettings & s)
{
s.setValue (...);
}
};
int main (...)
{
Params p;
p.loadGlobal ();
QSettings bak ("myparams.ini", ...);
p.saveTo (bak);
}
But I am looking for a solution without modifying the Params class.
Well, no, QT Doesn't really support this directly. I think your best bet is writing a helper class...something like:
void copySettings( QSettings &dst, QSettings &src )
{
QStringList keys = src.allKeys();
for( QStringList::iterator i = keys.begin(); i != keys.end(); i++ )
{
dst.setValue( *i, src.value( *i ) );
}
}
I think there are 2 issues:
QSettings does not have a copy constructor or assignment operator (that I know of), so you'll probably have to write your own copy using allKeys().
You can't save QSettings to an arbitrary file, but what you can do is set the path used for a specific format and scope using the static method QSettings::setPath(). Note that you need to do that before your backup QSettings object is created (and you would use format IniFormat).
If you're OK not having complete control over the resulting path, this should be sufficient. If not, you could still do the above, then get the file name using fileName() and use a system call to copy/move the file to the desired final location.

c++ managed class constructor can not have parameters?

please help me out , why my code cannot compile,
the compiler complains that:
error C2629: 意外的“StringToAnsi (”
error C2334: “{”的前面有意外标记;跳过明显的函数体
error C2629: 意外的“StringToAnsi (”
...
Here is my code:
#using <System.dll>
#using <mscorlib.dll>
class StringToAnsi
{
private:
void * m_ptr;
public:
StringToAnsi( System::Object ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(safe_cast<System::String^>(str)).ToPointer();
}
StringToAnsi(System::String ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer();
}
~StringToAnsi()
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(m_ptr));
}
operator const ACHAR*()
{
return (const ACHAR*)m_ptr;
}
Because you have two constructors with the same number of parameters. There is an Object and a String, but both are an Object. So this seems very ambiguous.
When you create two methods (or constructors), you can't let them have the same number of parameters, because the compiler doesn't know which one to call.
When you put in a string into the construction like so: new StringToAnsi("bla"). The compiler doesn't know which constructor to use.

Is it possible to define a generic type Vector in Actionsctipt 3?

Hi i need to make a VectorIterator, so i need to accept a Vector with any type. I am currently trying to define the type as * like so:
var collection:Vector.<*> = new Vector<*>()
But the compiler is complaining that the type "is not a compile time constant". i know a bug exists with the Vector class where the error reporting, reports the wrong type as missing, for example:
var collection:Vector.<Sprite> = new Vector.<Sprite>()
if Sprite was not imported, the compiler would complain that it cannot find the Vector class. I wonder if this is related?
So it looks like the answer is there is no way to implicitly cast a Vector of a type to valid super type. It must be performed explicitly with the global Vector.<> function.
So my actual problem was a mix of problems :)
It is correct to use Vector. as a generic reference to another Vector, but, it cannot be performed like this:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = spriteList // this will cause a type casting error
The assignment should be performed using the global Vector() function/cast like so:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = Vector.<Object>(spriteList)
It was a simple case of me not reading the documentation.
Below is some test code, I would expect the Vector. to cast implicitly to Vector.<*>.
public class VectorTest extends Sprite
{
public function VectorTest()
{
// works, due to <*> being strictly the same type as the collection in VectorContainer
var collection:Vector.<*> = new Vector.<String>()
// compiler complains about implicit conversion of <String> to <*>
var collection:Vector.<String> = new Vector.<String>()
collection.push("One")
collection.push("Two")
collection.push("Three")
for each (var eachNumber:String in collection)
{
trace("eachNumber: " + eachNumber)
}
var vectorContainer:VectorContainer = new VectorContainer(collection)
while(vectorContainer.hasNext())
{
trace(vectorContainer.next)
}
}
}
public class VectorContainer
{
private var _collection:Vector.<*>
private var _index:int = 0
public function VectorContainer(collection:Vector.<*>)
{
_collection = collection
}
public function hasNext():Boolean
{
return _index < _collection.length
}
public function get next():*
{
return _collection[_index++]
}
}
[Bindable]
public var selectedItems:Vector.<Category>;
public function selectionChange(items:Vector.<Object>):void
{
selectedItems = Vector.<Category>(items);
}
I believe you can refer to an untyped Vector by just calling it Vector (no .<>)
With Apache Flex 4.11.0, you can already do what you want. It might have been there since 4.9.0, but I have not tried that before.
var collection:Vector.<Object> = new Vector.<Object>()
maybe?
But i'm just speculating, haven't tried it.
var collection:Vector.<Object> = new Vector.<Object>()
but only on targeting flash player 10 cs4

Resources