Get the actual type of a generic object parameter

前端 未结 2 506
攒了一身酷
攒了一身酷 2021-01-04 19:34

No doubt elements of this question have been asked before, but I\'m having trouble finding an answer. (Disclaimer: this is related, but separate from a recent question I as

相关标签:
2条回答
  • 2021-01-04 20:05

    This should give you a callable method (I'll test it in a little while). The boxing/unboxing it incurs is much faster than the security checks required for the Reflection API invocation (which happens to also require boxing).

    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();
    }
    
    0 讨论(0)
  • 2021-01-04 20:17

    You're in luck. I actually had to do something very similar a few weeks ago.

    For a detailed explanation see the above blog post, but basically the general idea is to reflect the type and manually invoke the method with an explicit set of parameters.

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

    It's not very type safe, but it does exactly what you're looking for.

    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 });
        }
    
    }
    

    Output

       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
    
    0 讨论(0)
提交回复
热议问题