Getting value of public static field/property of a class by it's name as string in dart via reflectable - reflection

Say I have a class:
class Icons {
static const IconData threesixty = IconData(0xe577, fontFamily: 'MaterialIcons');
}
now I have a string variable with value of "threesixty":
String fieldName = "threesixty";
how can I get the value of the threesixty in Icons class by the fieldName variable?
I am using the reflectable package and already have used other features of ClassMirrors in flutter but don't know how to do this.

What you want requires use of reflection. In flutter reflection is not supported because of tree shaking. Tree shaking is the process of removing unused code from your app package (apk, ipa) in order to reduce the package size. When reflection is in use all code can be used implicitly so flutter won't be able to know which parts of code to get rid of, so they opted to not support reflection (mirrors in dart context).
You should try to solve your problem with inheritance if possible, or depending on your specific problem you can try to utilize static code generation.
Edit: You can invoke a static getter with reflectable like this;
import 'package:reflectable/reflectable.dart';
class Reflector extends Reflectable {
const Reflector() : super(staticInvokeCapability);
}
const reflector = const Reflector();
#reflector
class ClassToReflect {
static double staticPropertyToInvoke = 15;
}
Main.dart
import 'package:reflectable/reflectable.dart';
import 'main.reflectable.dart';
void main() {
initializeReflectable();
ClassMirror x = reflector.reflectType(ClassToReflect);
var y = x.invokeGetter('staticPropertyToInvoke');
debugPrint(y);
}
P.S. main.reflectable.dart is the file generated by reflectable package.

As far as I know this is not possible unless using a mirror library.
See:
Get access to an object's property using bracket notation in dart

Related

How Poco::SharedLibrary loading and instantiating classes?

I know that dynamic libraries can be loaded by Poco::SharedLibrary as below:
using PocoLibraryPtr = std::shared_ptr<Poco::SharedLibrary>;
poco_library = PocoLibraryPtr(new Poco::SharedLibrary(library_path));
I see in the code that the class is instantiated directly after loading. Is this feasible? Currently this code works fine.
template <typename ClassObject, typename Base>
class ClassFactory : public AbstractClassFactory<Base> {
public:
ClassFactory(const std::string& class_name,
const std::string& base_class_name)
: AbstractClassFactory<Base>(class_name, base_class_name) {}
Base* CreateObj() const { return new ClassObject; }
};
When the class is loaded, then the code use
classobj = factory->CreateObj();
to create the class. I did not find similar usage online. Is there any code I didn't notice?
It looks like you want a shared library to create an object using a templatized factory class.
Template instantiations are static polymorphic so the factory object needs to be determined at compile time.
In other words, no, that won't work.
If you specifically want Poco SharedLibrary help, take a look at the Poco documentation for more help: https://pocoproject.org/docs/Poco.SharedLibrary.html.
Or look at the slides here: https://pocoproject.org/slides/120-SharedLibraries.pdf

Access objects instantiated in Flex app's MXML file in other AS classes

I've got an object declared and instantiated in my Flex application's singular MXML file:
public var CDN:CDNClass = new CDNClass;
I would like to access this same CDN object (and its public methods and properties) in another class declared in a separate .as file as such:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
But when I try to access the public method parsePlayList in the CDN object in a method in the class defined in the .as file, I get the following error:
Access of undefined property CDN
The reason I want to do this is to break up the logic of my application into multiple AS files and have minimal MXML files, probably only one.
Thanks - any help is much appreciated. Perhaps my OOD/OOP thinking is not correct here?
IT depends on your class architecture. For your code to work, the CDNClass instance must be defined and implemented inside your SyncConnectorManager.
Generally, you can always call down into components, but should never call up
One option is to pass the instance ofCDNClass to a variable inside SyncConnectorManager. Add this variable to your SyncConnectionManager class:
public var CDN:CDNClass = new CDNClass;
And at some point do this:
syncConnectorManagerInstance.CDN = CDN;
That way both classes will have access to the same CDN instance and can call methods on it.
Yes, your OOP thinking is not correct here. You should take in mind differences between classes and instances. This line declares a filed in a current class and initiates it with an instance:
public var CDN:CDNClass = new CDNClass;
So current instance of your MXML class (you can think about it as usual AS class with some other notation) has public field. To operate with CDN instance you need something from the following:
Read the value of CDN (as far as it is public) from the instance of your MXML class. You need some reference to it for that.
The instance of your MXML class can have a reference to the instance of SyncConnectorManager and SyncConnectorManager should have a way to inject the value of CDN there. Something like:
Your class:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private var CDN:CDNClass;
public function SyncConnectorManager(CDN:CDNClass)
{
this.CDN = CDN;
}
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
In your case SyncConnectorManager class hasn't CDN declared (the problem of the compiler error you mentioned) and instantiated (the problem of NPE even if you just declare field).
As the bottom line I can suggest you to follow ActionScript naming and coding conventions to talk other people and team members about your code :)

Pass a C++/CLI wrapper of a native type to another C++/CLI assembly

Suppose I have the following simple wrapper of a NativeClassInstance.
public ref class Wrapper
{
private:
NativeClass *_wrapped;
public:
Renderer()
{
_wrapped = new NativeClass();
}
~Renderer()
{
delete _wrapped;
}
operator NativeClass*()
{
return _wrapped;
}
}
Now, I want to create an instance of Wrapper from C# with Wrapper wrapper = new Wrapper() and use it in another native functionalities wrapper that resides in another assembly with Helper.Foo(wrapper) (nothing strange having other functionalities not directly related to the wrapped classes in another assembly, IMO):
// Utilities is in another Assembly
public ref class Helper
{
public:
static Foo(Wrapper ^wrapper)
{
// Do something in native code with wrapper->_wrapped
}
}
The results with the implicit user conversion is:
candidate function(s) not accessible
If I make _wrapped public it is:
cannot access private member declared in class ...
Now, I've learnt that native type visibility is private outside of the assembly. So, how I'm supposed to use the wrapped entity in native code outside the assembly it's defined? I've read of make_public but you can't use with template types so it seems very limiting in the general case. Am I missing something? Is there a more correct solution?
I haven't been able to successfully expose native types using make_public, however a solution I have used is to put NativeClass in its own native DLL and then a) reference the native DLL from both assemblies; and b) pass the pointer to the native class around as an IntPtr.
Under the above scenario, instead of having an operator NativeClass* you might use a property such as
property IntPtr WrappedObject {
IntPtr get() { return IntPtr(_wrapped); }
}
You then retrieve NativeObject in you helper assembly by
static void Foo(Wrapper ^wrapper)
{
NativeObject *_wrapped
= static_cast<NativeObject*>(wrapper->WrappedObject.ToPointer());
// ... do something ...
}
If you use make_public, your solution of making _wrapped public should work (it would obviously be best to make a public accessor instead). Regarding your comment "I've read of make_public but you can't use with template types so it seems very limiting in the general case." I agree--read here for the workaround I used:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/b43cca63-b0bf-451e-b8fe-74e9c618b8c4/
More related info:
Best workaround for compiler error C2158: make_public does not support native template types
Good luck!

Flex: How to use flashvars from different classes

I am just learning actionscript, so come across the problem
In my application I often call to different web services, and because I don't want to hardcode urls to them in my code, I am passing urls to the services as flashvars.
Currently I am doing it this way:
public var siteUrl:String;
public var gameId:String;
public function main():void
{
siteUrl = Application.application.parameters.siteurl;
gameId = Application.application.parameters.gameid;
Where main is a function, which is called on application's creation complete event.
This way I can call both variables from main file of the application but I want to access them from other files. (other as classes)
So is there a way to create class with constants and init values there with flashvars so I can use them everywhere (after importing of course)
The parameters are just stored in that Application.application.parameters object, and that's static. There's no reason you couldn't access that from other classes in your code.
If you want to write a class that wraps the parameters (maybe validates them or something) you could do that fairly easily. You can use a for each loop to loop over all the parameters. Something like:
var params:Object = Application.application.parameters
for(var name:String in params) {
var value:String = params[name] as String;
/* do something with the param */
}
If you want your class to actually verify things then it could just check for each parameter it expects and store it in a local variable.
It really just depends on your own preferences. Some people are fine with accessing the parameters object when they need it. Some people like having the extra code-completion by having a config class that actually defines all the expected config variables.
Update in response to comment:
Instead of having one module declare the variable and have other modules have to depend on that one to access the property it would be cleaner to have a single config module that everything that needs it would all use.
You could use a static class or singleton or some IoC stuff. Just for simplicity I'll show you a way you can do it with a static class.
class MyConfig {
private static var _infoService:String;
private static var _someOtherParam:int;
public static function get infoService():String { return _infoService; }
public static function get someOtherParam():int { return _someOtherParam; }
public static function initParams():Void {
var params:Object = Application.application.parameters;
_infoService = params.infoservice;
// just assuming you have a method to convert here. don't remember the
// code off the top of my head
_someOtherParam = convertToInt(params.someOtherParam);
}
}
Make sure when your app initializes it calls MyConfig.initParams(). You can have that method actually validate that it gets everything it expects and throw exceptions (or return an error) if there's a failure if you want.
Then wherever you need to use that config within your code you just import your config class and access the param. So getting infoService would just be:
var infoService:String = MyConfig.infoService;
Personally I wouldn't use a static class, but it was the easiest to show.

Flex: AMF and Enum Singletons – can they play well together?

I'm using Python+PyAMF to talk back and forth with Flex clients, but I've run into a problem with the psudo-Enum-Singletons I'm using:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
}
When I'm using locally created instances, everything is peachy:
if (someInstance.type == Type.EMPTY) { /* do things */ }
But, if 'someInstance' has come from the Python code, it's instance of 'type' obviously won't be either Type.EMPTY or Type.FULL.
So, what's the best way to make my code work?
Is there some way I can control AMF's deserialization, so when it loads a remote Type, the correct transformation will be called? Or should I just bite the bullet and compare Types using something other than ==? Or could I somehow trick the == type cohesion into doing what I want?
Edit: Alternately, does Flex's remoting suite provide any hooks which run after an instance has been deserialized, so I could perform a conversion then?
Random thought: Maybe you could create a member function on Type that will return the canonical version that matches it?
Something like:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
// I'm assuming this is where that string passed
// in to the constructor goes, and that it's unique.
private var _typeName:String;
public function get canonical():Type {
switch(this._typeName) {
case "empty": return EMPTY;
case "full": return FULL;
/*...*/
}
}
}
As long as you know which values come from python you would just convert them initially:
var fromPython:Type = /*...*/
var t:Type = fromPython.canonical;
then use t after that.
If you can't tell when things come from python and when they're from AS3 then it would get pretty messy, but if you have an isolation layer between the AS and python code you could just make sure you do the conversion there.
It's not as clean as if you could control the deserialization, but as long as you've got a good isolation layer it should work.

Resources