代码之家  ›  专栏  ›  技术社区  ›  Matt Mitchell

获取泛型对象参数的实际类型

  •  8
  • Matt Mitchell  · 技术社区  · 15 年前

    我有这样一种方法:

    public static void Method<T>(MethodInfo m, T value)
    {
      Type memberType = m.GetValueType();
    
      if (memberType.IsAssignableFrom(typeof(List<T>))
      {
        object memberValue = Activator.CreateInstance(memberType);
        ((List<T>)memberValue).Add(value);
      }
    }
    

    当我这样称呼它时,它工作得很好:

    string s = "blah";
    Method(memberInfo, s);
    

    但是,我需要使用泛型类型调用此方法,因此我这样调用它:

    Type valueType = someType;
    object passValue = someMethod.MakeGenericMethod(new Type[] { valueType }).Invoke(this, new object[] { });
    /* Call my original method */
    Method(memberInfo, passValue );
    

    现在,intellisense知道方法中的“价值”<T>是valueType是什么类型(比如“FooObject”)。但是'T'是object,这意味着一个列表<FooObject>是 可从列表中分配<T>(即列表<对象>)。

    我已经尝试过在变量('passValue')上使用Convert.ChangeType,但是没有任何用处。

    最好的解决方案是不依赖IsAssignableFrom并对其是否有效进行松散的类型检查吗?问题是,除非'T'确实是memberValue的元素类型,否则我不确定是否能够正确地强制转换memberValue。

    2 回复  |  直到 15 年前
        1
  •  6
  •   Sam Harwell    15 年前

    这将为您提供一个可调用的方法(稍后我将对其进行测试)。它引起的装箱/拆箱是

    private static Action<MethodInfo, object> BuildAccessor(Type valueType)
    {
        MethodInfo genericMethod = null; // <-- fill this in
        MethodInfo method = genericMethod.MakeGenericMethod(new Type[] { valueType });
        ParameterExpression methodInfo = Expression.Parameter(typeof(MethodInfo), "methodInfo");
        ParameterExpression obj = Expression.Parameter(typeof(object), "obj");
    
        Expression<Action<MethodInfo, object>> expr =
            Expression.Lambda<Action<MethodInfo, object>>(
                Expression.Call(method, methodInfo, Expression.Convert(obj, valueType)),
                methodInfo,
                obj);
    
        return expr.Compile();
    }
    
        2
  •  5
  •   Nathan Taylor    15 年前

    你很幸运。我实际上 had to do something very similar 几周前。

    typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });
    

    非常

    class Program
    {
    
        static void Main(string[] args)
        {
            object str = "Hello World";
            object num = 5;
            object obj = new object();
    
            Console.WriteLine("var\tvalue\t\tFoo() Type\tCallFoo() Type");
            Console.WriteLine("-------------------------------------------------------");
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", "str", str, MyClass.Foo(str), MyClass.CallFoo(str));
            Console.WriteLine("{0}\t{1}\t\t{2}\t{3}", "num", num, MyClass.Foo(num), MyClass.CallFoo(num));
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", "obj", obj, MyClass.Foo(obj), MyClass.CallFoo(obj));
        }
    
    }
    
    class MyClass
    {
        public static Type Foo<T>(T param)
        {
            return typeof(T);
        }
    
        public static Type CallFoo(object param)
        {
            return (Type)typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });
        }
    
    }
    

    输出

       var     value           Foo() Type      CallFoo() Type
       -------------------------------------------------------
       str     Hello World     System.Object   System.String
       num     5               System.Object   System.Int32
       obj     System.Object   System.Object   System.Object