繁体   English   中英

C#反射:如何确定ParameterInfo是否是在父类上定义的泛型类型

[英]C# Reflection: How to determine if ParameterInfo is a generic type defined on parent class

我有这样的方法签名:

public class Class1<TItem>
{
    public void CopyTo(TItem[] items) { }
}

在父类上声明了TItem位置。

当我使用反射来解析此方法时:

// not returning TItem as generic in signature    
string sig = method.FullName; // ClassLibrary1.Class1`1.CopyTo(TItem[])

if (method.ContainsGenericParameters) // true
{
           Type[] genericArgs = method.GetGenericArguments(); // returns empty
           foreach (Type genericArg in genericArgs)
           {
               loM.cGenericParameters += genericArg.Name + ",";
           }
 }

我需要弄清楚泛型类型签名是什么,以便查看XML文档(需要构建时髦的泛型类型查找签名)。 我需要将方法签名映射到如下所示的XML文档中:

<member name="M:ClassLibrary1.Class1`1.CopyTo(`0[])">

我无法可靠地检测TItem []是否通用,并弄清楚如何(通常)获取通用索引。

当我查看参数签名时, ParameterType.IsGenericType.GenericParameterPosition一样为false。 ParameterType.ContainsGenericParameters为true,但是没有地方给我通用的原始类型签名(即,签名需要的'0[] ,通常在.FullName属性中看到)。

如果通用定义在实际方法上(即SomeMethod<TItem>(TItem[] blah) ,这一切都可以用,在这一点上我可以根据需要解析参数,但是当通用参数在类型上定义时,我可以不能通过其通用参数位置找出正确的签名来引用父通用类型。

我认为问题在于您正在查看方法的通用参数,而不是方法的参数。 您还必须区分数组和泛型类型。

if (method.ContainsGenericParameters)
{
    foreach (var parameter in method.GetParameters())
    {
        if (parameter.ParameterType.IsArray)
        {
            var elementType = parameter.ParameterType.GetElementType();

            var genericArgName = elementType.Name;
            var genericParameterPosition = elementType.GenericParameterPosition;
        }
        else if (parameter.ParameterType.IsGenericType)
        {
            foreach (var genericArg in parameter.ParameterType.GetGenericArguments())
            {
                var genericArgName = genericArg.Name;
                var genericParameterPosition = genericArg.GenericParameterPosition;

                // If you need to differentiate between a generic arg that is declared
                // in the method versus being declared in the class/interface/struct:
                if (genericArg.DeclaringMethod == null)
                {
                    // Declared in the class/interface/struct
                }
                else
                {
                    // Declared in the method
                }
            }
        }
    }
}

当您在下面使用Class2<>.Foo<>类的东西时,事情会变得有些奇怪-对于foreach循环的两次迭代, genericArg变量的GenericParameterPosition0 检查DeclaringMethod属性是否为空值,以确定该位置所指的是:方法或类/接口/结构。

public class Class2<TKey>
{
    public void Foo<TValue>(IDictionary<TKey, TItem> items) { }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM