【问题标题】:Access static method from GenericClass<T> where T is given by a Type instance从 GenericClass<T> 访问静态方法,其中 T 由 Type 实例给出
【发布时间】:2013-04-02 15:30:13
【问题描述】:

我有一个带有静态方法的泛型类,该方法使用类型参数:

GenericClass<T>
{
    public static void Method()
    {
        //takes info from typeof(T)
    }
}

现在,我需要访问该静态方法,而不是简单地使用GenericClass&lt;KnownType&gt;.Method()。我需要有一个 Type 实例来做到这一点。所以:

public void OutsiderMethod(Type T)
{
    GenericClass<T>.Method() 
    //it's clear this line won't compile, for T is a Type instance
    //but i want some way to have access to that static method.
}

使用反射,我可能可以使用一些 MethodInfo 的东西通过它的字符串名称来调用该方法。 这部分好,解决了问题。 但如果可能的话,我希望不必将名称用作字符串。

有人吗???

【问题讨论】:

  • 这种情况下扩展方法不是更合适吗?
  • 这需要一个 GenericClass 的实例,T 由 Type 实例给出。

标签: c# generics reflection types static


【解决方案1】:

这是一个使用表达式的例子:

public static class GenericHelper
{
    public static object Invoke(Expression<Action> invokeMethod, object target, Type genericType, params object[] parameters)
    {
        MethodInfo methodInfo = ParseMethodExpression(invokeMethod);
        if (!methodInfo.DeclaringType.IsGenericType)
            throw new ArgumentException("The method supports only generic types");
        Type type = methodInfo.DeclaringType.GetGenericTypeDefinition().MakeGenericType(genericType);
        MethodInfo method = type.GetMethod(methodInfo.Name);
        return method.Invoke(target, parameters);
    }

    public static object Invoke(Expression<Action> invokeMethod, Type genericType, params object[] parameters)
    {
        return Invoke(invokeMethod, null, genericType, parameters: parameters);
    }

    private static MethodInfo ParseMethodExpression(LambdaExpression expression)
    {
        Validate.ArgumentNotNull(expression, "expression");
        // Get the last element of the include path
        var unaryExpression = expression.Body as UnaryExpression;
        if (unaryExpression != null)
        {
            var memberExpression = unaryExpression.Operand as MethodCallExpression;
            if (memberExpression != null)
                return memberExpression.Method;
        }
        var expressionBody = expression.Body as MethodCallExpression;
        if (expressionBody != null)
            return expressionBody.Method;
        throw new NotSupportedException("Expession not supported");
    }
}

方法调用如下所示:

GenericHelper.Invoke(() => GenericClass<object>.Method(), typeof(string));

【讨论】:

    【解决方案2】:

    非泛型类的泛型方法比泛型类的非泛型方法更容易访问。

    您可以创建一个简单地调用真实方法的辅助方法:

    void OutsiderMethodHelper<T>()
    {
        GenericClass<T>.Method();
    }
    

    然后您可以获取该方法的MethodInfo,而无需通过名称作为字符串进行查找:

    public void OutsiderMethod(Type T)
    {
        Action action = OutsiderMethodHelper<object>;
        action.Method.GetGenericMethodDefinition().MakeGenericMethod(T).Invoke(null, null);
    }
    

    【讨论】:

    • 嗯,听起来不错!!我会测试它。同时,新手问题:是否真的需要创建代表?当MakeGenericMethod 出现在Method 中时为什么GetGenericMethodDefinition ???
    • 有没有我可以找到的反思文献来更好地学习它?
    • @Daniel C# 允许您在不调用函数的情况下引用函数的情况并不多,创建委托就是这样一种情况,而且可能是最简单的情况。委托代表OutsiderMethodHelper&lt;object&gt;GetGenericMethodDefinition() 为您提供MethodInfo 代表OutsiderMethodHelper&lt;&gt;MakeGenericMethod 允许您填写类型参数。如果你跳过GetGenericMethodDefinition(),你会得到一个异常,因为OutsiderMethodHelper&lt;object&gt; 没有任何需要填充的泛型类型参数。
    • @Daniel 我会说“试试看”。反射属性和函数表现良好,并且几乎总是会在您做错了什么时让您知道,但有一个有用的描述例外。反正我就是这样捡的。 :)
    猜你喜欢
    • 1970-01-01
    • 2016-02-25
    • 2023-03-07
    • 2014-07-06
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多