다음을 통해 공유


Dynamic Method Invocation with Generics

So I decided to test a theory of mine.

The theory was could I stream line method invocation to function the same for methods that contain generic type parameters as invocation for non-generic method.

I know if the method is defined "statically", a dynamic object will call it, but I wanted a centralized way to handle method invocation on dynamic object.

As it stand now, this is LEGAL:

01.public class  Dog : DynamicObject
02.{
03.    public override  bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out  object result)
04.    {
05.        //Do some code
06.    }
07.}
08. 
09.//Then in your code elsewhere....
10. 
11.dynamic puppy = new  Dog();
12. 
13.puppy.Mate(); //LEGAL

This is also LEGAL

01.public class  Dog : DynamicObject
02.{
03.    public void  Mate()
04.    {
05.        //Do some code
06.    }
07.     
08.    public override  bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out  object result)
09.    {
10.        //Do some code
11.    }
12.}
13. 
14.//Then in your code elsewhere....
15. 
16.dynamic puppy = new  Dog();
17. 
18.puppy.Mate(); //LEGAL - calls the statically defined method and will NOT trigger the "Try" method

And this is LEGAL (notice the generic parameter on Mate method)

01.public class  Dog : DynamicObject
02.{
03.    public void  Mate<T>()
04.    {
05.        //Do some code
06.    }
07.     
08.    public override  bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out  object result)
09.    {
10.        //Do some code
11.    }
12.}
13. 
14.//Then in your code elsewhere....
15. 
16.dynamic puppy = new  Dog();
17. 
18.puppy.Mate<German>(); //LEGAL - calls the statically defined method and will NOT trigger the "Try" method

However......this is NOT LEGAL (notice the method invocation w/ generic parameter)

01.public class  Dog : DynamicObject
02.{   
03.    public override  bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out  object result)
04.    {
05.        //Do some code
06.    }
07.}
08. 
09.//Then in your code elsewhere....
10. 
11.dynamic puppy = new  Dog();
12. 
13.puppy.Mate<GermanShepard>(); //ILLEGAL!!!!!! Not statically defined and the "Try" function will not pick up the generic type parameter

Until now.....

I've created an infrastructure that will allow you to do the latter. I created a new object that implements the IDynamicMetaObjectProvider and adds additional "Try" methods that capture the generic parameter. I also created interfaces that allow your object to participate in dynamics even if it can't inherit from my "base dynamic object".

My object is called BaseDynamic, and it is an abstract class that must be inherited from. I extend the TryInvoke and and TryInvokeMember methods (16 for each). Granted the TryInvoke does not allow generic invocation under normal circumstances, but i mirrored the functionality should Microsoft ever allow it as apart of the DLR. I keep the naming convention Microsoft used so all you have to is replace where ever you are using DynamicObject with BaseDynamic and your code should still work since I duplicate existing functionality along with extend it.

Ex. (notice the different generic parameters)

01.public class  Dog : BaseDynamic
02.{   
03.    public override bool TryInvokeGenericMember<Param1>(InvokeMemberBinder binder, object[] args, out object result)
04.    {
05.        //Do some code
06.    }
07.     
08.    public override  bool TryInvokeGenericMember<Param1, Param2, Param3>(InvokeMemberBinder binder, object[] args, out  object result)
09.    {
10.        //Do some code
11.    }
12.}
13. 
14.//Then in your code elsewhere....
15. 
16.dynamic puppy = new  Dog();
17. 
18.puppy.Mate<German>(); //Now LEGAL!!!!!!
19. 
20.puppy.SetInfo<Name, Address, Owner>(PuppyName, PuppyAddr, PuppyOwner); // Now LEGAL!!!!

And if you wish to participate in dynamic generics but can't inherit from my BaseDynamic object, then simply implement one of the many interfaces and activate dynamics on the object.

01.public class  Dog : IBaseDynamicGeneric2
02.{
03.    public bool  TryInvokeGenericMember<Param1, Param2>(InvokeMemberBinder binder, object[] args, out  object result)
04.    {
05.        //Do some code
06.    }
07. 
08.    bool TryInvokeGeneric<Param1, Param2>(InvokeBinder binder, object[] args, out  object result)
09.    {
10.        throw new  NotImplementedException()
11.    }
12. 
13.}
14. 
15.//Then in your code elsewhere use must "activate" the dynamic infrastructure for your object.
16. 
17.Dog puppy = new  Dog();
18. 
19.dynamic dPuppy = BaseDynamic.ActivateDynamics(puppy);
20. 
21.dPuppy.SetParents<Pitbull, GermanShepherd>();

Here's my basic website where the open source code can be downloaded: Chizor.com