10

次のようなクラスがあるとします。

public class MyClass<T>
{
    public void Foo(T t)
    {
    }
}

ここで、 のインスタンスとMyClass<int>そのMethodInfoメソッドFooの があるとします。を呼び出すと、 type を参照する 1 つのエントリをmethodInfo.GetParameters()持つ配列が返されます。私の問題は、そのパラメーターがクラスで宣言されているか、またはとして宣言されているかがわからないことです。 ParameterInfointintT

私は何を達成しようとしていますか?実行時に、 Visual Studio で生成された XML Doc ファイルから、 で
指定されたメソッドのドキュメントを読みたいと考えています。 上記で定義されたメソッドの場合、キーは次のようになります。MethodInfo

<namespace>.MyClass`1.Foo(`0)

`0、宣言クラスの最初のジェネリック型パラメーターを参照します。この文字列を作成できるようにするには、何らかの方法でこの情報を取得する必要があります。
しかし、どのように? MethodInfoその情報は含まれていないようです...

4

4 に答える 4

3

キーType.ContainsGenericParametersはパラメータタイプにあるようです:

与えられた

public class MyClass<T>
{
    public void Foo(T t)
    {
    }

    public void Bar(int i)
    {

    }
}

それで

class Program
{
    static void Main(string[] args)
    {
        var obj = new MyClass<int>();

        // Closed type
        var closedType = obj.GetType();

        // Open generic (typeof(MyClass<>))
        var openType = closedType.GetGenericTypeDefinition();

        // Methods on open type
        var fooT = openType.GetMethod("Foo");
        var barint = openType.GetMethod("Bar");

        // Parameter types
        var tInFoo = fooT.GetParameters()[0].ParameterType;
        var iInBar = barint.GetParameters()[0].ParameterType;

        // Are they generic?
        var tInFooIsGeneric = tInFoo.ContainsGenericParameters;
        var iInBarIsGeneric = iInBar.ContainsGenericParameters;

        Console.WriteLine(tInFooIsGeneric);
        Console.WriteLine(iInBarIsGeneric);

        Console.ReadKey();
    }
}

出力

True
False

これは明らかに過負荷などのためにより多くの作業を必要とします。

于 2012-11-22T11:16:47.077 に答える
1

.Net のリフレクションの代わりに Mono.Cecil を使用することを検討したかどうかはわかりません。

// Gets the AssemblyDefinition (similar to .Net's Assembly).
Type testType = typeof(MyClass<>);
AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(new Uri(testType.Assembly.CodeBase).LocalPath);
// Gets the TypeDefinition (similar to .Net's Type).
TypeDefinition classDef = assemblyDef.MainModule.Types.Single(typeDef => typeDef.Name == testType.Name);
// Gets the MethodDefinition (similar to .Net's MethodInfo).
MethodDefinition myMethodDef = classDef.Methods.Single(methDef => methDef.Name == "Foo");

その後、myMethodDef.FullName戻ります

"System.Void MyNamespace.MyClass`1::Foo(System.Int32,T,System.String)"

そしてclassDef.GenericParameters[0].FullName戻る

"T"

Mono.Cecil は、ジェネリック、ネストされたクラス、および配列を記述する別の方法を使用することに注意してください。

List[T] => List<T>
MyClass+MyNestedClass => MyClass/MyNestedClass
int[,] => int[0...,0...]
于 2012-11-22T09:37:07.210 に答える
1

Type.GetGenericTypeDefinition メソッドを介してジェネリック クラスの定義を取得し、同じメソッドの定義を名前 (およびシグネチャ) で見つけて、比較Foo(T t)してFoo(int t)ください。

MyClass<int> c = new MyClass<int>();

Type concreteType = c.GetType();
Console.Write("Concrete type name:");
Console.WriteLine(concreteType.FullName);
Console.WriteLine();

MethodInfo concreteMethod = concreteType.GetMethod("Foo");
if (concreteMethod != null)
{
    Console.WriteLine(concreteMethod.Name);
    foreach (ParameterInfo pinfo in concreteMethod.GetParameters())
    {
        Console.WriteLine(pinfo.Name);
        Console.WriteLine(pinfo.ParameterType);
        Console.WriteLine();
    }
    Console.WriteLine();
}

if (concreteType.IsGenericType)
{
    Console.Write("Generic type name:");
    Type genericType = concreteType.GetGenericTypeDefinition();
    Console.WriteLine(genericType.FullName);
    Console.WriteLine();

    MethodInfo genericMethod = genericType.GetMethod("Foo");
    if (genericMethod != null)
    {
        Console.WriteLine(genericMethod.Name);
        foreach (ParameterInfo pinfo in genericMethod.GetParameters())
        {
            Console.WriteLine(pinfo.Name);
            Console.WriteLine(pinfo.ParameterType);
            Console.WriteLine();
        }
        Console.WriteLine();
    }
}
于 2012-10-28T12:17:27.103 に答える