c# - DynamicObject. How execute function through TryInvoke? -
i want execute static functions through dynamicobject, don't know how execute saveoperation without specifying class name typeof(test1)
or typeof(test2)
. how relise better?
for example
class dynobj : dynamicobject { getmemberbinder saveoperation; public override bool trygetmember(getmemberbinder binder, out object result) { saveoperation = binder; result = this; return true; } public override bool tryinvoke(invokebinder binder, object[] args, out object result) { type mytype = typeof(test1 or test2 or ....); result = mytype.getmethod(saveoperation.name).invoke(null, args); return true; } } class program { static void main(string[] args) { dynamic d1 = new dynobj(); d1.func1(3,6); d1.func2(3,6); } } class test1 { public static void func1(int a, int b){...} } class test2 { public static void func2(int a, int b){ ...} }
second way defines static function attribute ( offered carnifex )
class test3 { [dynfuncmemberattribute] public static void func3(int a, int b){...} }
and type
public override bool tryinvoke(invokebinder binder, object[] args, out object result) { type mytype = null; foreach (type types in assembly.getexecutingassembly().gettypes()) { foreach (methodinfo mi in types.getmethods()) { foreach (customattributedata cad in mi.customattributes) { if (cad.attributetype == typeof(dynfuncmemberattribute)) { mytype = types; break; } } } } result = (mytype != null)? mytype.getmethod(saveoperation.name).invoke(null, args): null; return mytype != null; }
you use attributes , set eg. [dynfuncmemberattribute] class or method self.
then inside tryinvoke (or constructor) types/methods marked attribute, build map/cache , voila :)
edit: example of use attribute. remember buildcache() throw exception if 2 method same name found.
[attributeusage(attributetargets.method)] class dynfuncmemberattribute : attribute { } class dynobj : dynamicobject { dictionary<string, methodinfo> cache; getmemberbinder saveoperation; public override bool trygetmember(getmemberbinder binder, out object result) { saveoperation = binder; result = this; return true; } public override bool tryinvoke(invokebinder binder, object[] args, out object result) { if (cache == null) cache = buildcache(); methodinfo mi; if (cache.trygetvalue(saveoperation.name, out mi)) { result = mi.invoke(null, args); return true; } result = null; return false; } private dictionary<string, methodinfo> buildcache() { return assembly.getentryassembly() .gettypes() .selectmany(t => t.getmethods(bindingflags.public | bindingflags.static)) .where(mi => mi.getcustomattribute<dynfuncmemberattribute>() != null) .todictionary(mi => mi.name); } } class program { static void main(string[] args) { dynamic d1 = new dynobj(); d1.func1(3, 6); d1.func2(3, 6); } } class test1 { [dynfuncmember] public static void func1(int a, int b) { console.writeline("func1"); } } class test2 { [dynfuncmember] public static void func2(int a, int b) { console.writeline("func2"); } }
Comments
Post a Comment