获取动态对象中方法的generics调用类型

我开始使用.Net中的动态对象,我无法弄清楚如何做某事。

我有一个inheritance自DynamicObject的类,我重写了TryInvokeMember方法。

例如

class MyCustomDynamicClass : DynamicObject { public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { // I want to know here the type of the generic argument } } 

在该方法中,我想知道调用中generics参数的类型(如果有的话)。

例如,如果我调用以下代码,我想在动态对象的覆盖方法中获取System.Boolean和System.Int32的值

 dynamic myObject = new MyCustomDynamicClass(); myObject.SomeMethod("arg"); myObject.SomeOtherMethod("arg"); 

目前,如果我在覆盖方法中放置一个断点,我可以得到被调用方法的名称(“SomeMethod”和“SomeOtherMethod”,以及参数的值,但不是generics类型)。

我怎样才能获得这些价值?

谢谢!

实际上,我查看了binder的层次结构,并在对象的内部字段中找到了具有所需值的属性。

问题是该属性未公开,因为它使用C#特定的代码/类,因此必须使用Reflection访问属性。

我在这个日本博客中找到了代码: http : //neue.cc/category/programming (我不读任何日语,因此我不确定作者是否真的描述了同样的问题

这是片段:

 var csharpBinder = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder"); var typeArgs = (csharpBinder.GetProperty("TypeArguments").GetValue(binder, null) as IList); 

typeArgs是一个列表,包含调用方法时使用的generics参数的类型。

希望这有助于其他人。

有点谷歌搜索,我有非常通用的.NET和Mono解决方案:

 /// Framework detection and specific implementations. public static class FrameworkTools { private static bool _isMono = Type.GetType("Mono.Runtime") != null; private static Func> _frameworkTypeArgumentsGetter = null; /// Gets a value indicating whether application is running under mono runtime. public static bool IsMono { get { return _isMono; } } static FrameworkTools() { _frameworkTypeArgumentsGetter = CreateTypeArgumentsGetter(); } private static Func> CreateTypeArgumentsGetter() { if (IsMono) { var binderType = typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.GetType("Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder"); if (binderType != null) { ParameterExpression param = Expression.Parameter(typeof(InvokeMemberBinder), "o"); return Expression.Lambda>>( Expression.TypeAs( Expression.Field( Expression.TypeAs(param, binderType), "typeArguments"), typeof(IList)), param).Compile(); } } else { var inter = typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.GetType("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder"); if (inter != null) { var prop = inter.GetProperty("TypeArguments"); if (!prop.CanRead) return null; var objParm = Expression.Parameter(typeof(InvokeMemberBinder), "o"); return Expression.Lambda>>( Expression.TypeAs( Expression.Property( Expression.TypeAs(objParm, inter), prop.Name), typeof(IList)), objParm).Compile(); } } return null; } /// Extension method allowing to easyly extract generic type arguments from . /// Binder from which get type arguments. /// List of types passed as generic parameters. public static IList GetGenericTypeArguments(this InvokeMemberBinder binder) { // First try to use delegate if exist if (_frameworkTypeArgumentsGetter != null) return _frameworkTypeArgumentsGetter(binder); if (_isMono) { // In mono this is trivial. // First we get field info. var field = binder.GetType().GetField("typeArguments", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); // If this was a success get and return it's value if (field != null) return field.GetValue(binder) as IList; } else { // In this case, we need more aerobic :D // First, get the interface var inter = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder"); if (inter != null) { // Now get property. var prop = inter.GetProperty("TypeArguments"); // If we have a property, return it's value if (prop != null) return prop.GetValue(binder, null) as IList; } } // Sadly return null if failed. return null; } } 

玩得开心。 顺便说一下,Impromptu很酷,但我不能使用它。

开源框架Dynamitey可以使用DLR调用internal / protected / private的属性,因此可以使用Silverlight。 但是接口显式成员有点棘手,因为你必须在类型上使用成员的实际全名,而不是接口成员名。 所以你可以这样做:

 var typeArgs = Dynamic.InvokeGet(binder, "Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder.TypeArguments") as IList;