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

时间:2015-12-13 02:17:30

标签: c# generics reflection

我有这样的方法签名:

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

在父类中声明TItem

当我使用Reflection解析此方法时:

// 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一样是假的。 ParameterType.ContainsGenericParameters是真的,但它没有给我一般的原始类型签名(即签名所需的'0[],通常在.FullName属性中看到。)

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

1 个答案:

答案 0 :(得分:1)

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

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<>下面的内容时,事情变得有点奇怪 - genericArg变量GenericParameterPosition 0 foreach DeclaringMethod }循环。检查public class Class2<TKey> { public void Foo<TValue>(IDictionary<TKey, TItem> items) { } } 属性是否有空值以确定该位置引用的内容:方法或类/接口/结构。

<?php 
$faker = Faker\Factory::create();

$I = new ApiTester($scenario);
$I->wantTo('create a new user');
$I->useToken();
$I->sendPost('users', [
    "first_name"    => "Test",
    "last_name"     => "Test",
    "email"         => 'test@test.com',
    "password"      => "testing",
    "role"          => "1"
]);
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
$I->seeResponseContainsJson(['status' => 'success']);
$I->seeResponseContainsJson(['data' => [
    'first_name' => 'Test'
]]);
$I->seeInDatabase('user', [
    "first_name"    => "Test",
    "last_name"     => "Test",
    "email"         => 'test@test.com'
]);