正确的 GetMethod 参数类型
Correct Parameter Type for GetMethod
在下面的代码中,我应该如何设置变量 "paramType" 以便它与 GetMethod() 调用中显示的方法匹配?
下面的代码与示例中的方法不匹配 class(methodInfo 为空)。
using System;
using System.Linq.Expressions;
public class MyClass<TClass>
{
public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
{
}
}
class Program
{
static void Main( string[] args )
{
var classType = typeof( MyClass<> );
// What should this really be?
var paramType = typeof( Expression<> ).MakeGenericType( typeof( Func<,> ) );
var methodInfo = classType.GetMethod( "MyMethod", new Type[] { paramType } );
}
}
编辑:我知道如何使用 GetMethods
或其他某种形式的迭代/假设来获得 MethodInfo
。我的问题具体是关于如何设置 paramType
的 System.Type
,如果它甚至可以为它生成 System.Type
。
编辑 2:为了更具体地解决问题,我更新了代码以增加风味:
using System;
using System.Linq.Expressions;
public class MyClass<TClass>
{
public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
{
Console.WriteLine( "Type: {0} Return: {1}", typeof( TClass ).Name, typeof( TMethod ).Name );
}
public void MyMethod<TMethod>( TMethod param )
{
}
}
class Program
{
public int MyProperty { get; set; }
static void Main( string[] args )
{
var classType = typeof( MyClass<> );
var typeClass = typeof( Program );
var typeMethod = typeof( int );
// What should this really be?
var paramType = typeof( Expression<> )
.MakeGenericType( typeof( Func<,> )
.MakeGenericType( typeClass, typeMethod )
);
var methodInfo = classType
.MakeGenericType( typeClass )
.GetMethod( "MyMethod", new Type[] { paramType } );
}
}
这也不起作用 - 这个包含更多信息的不同版本的 paramType
似乎不匹配。
在非一般情况下,有人可能想这样调用"MyMethod":
// I want to use a MethodInfo to perform this function:
new MyClass<Program>().MyMethod( _program => _program.MyProperty );
为此,您需要了解泛型类型,否则我认为您的任务将无法完成。
如果您的目的是在泛型 class 知道其任何类型之前为泛型创建一个泛型 methodinfo,以便您稍后可以调用 MakeGenericType
并使用您的两种类型,那将获胜不可能。
这可以通过调用 typeof(MyClass<>).GetMethod("MyMethod")
来显示,这将 return null。
另一方面,如果您知道具体类型,那很容易:
static MethodInfo GetMethod(Type classType, Type methodType)
{
var genericClassType = typeof(MyClass<>).MakeGenericType(classType);
var methodInfo = genericClassType.GetMethod("MyMethod");
var genericMethodInfo = methodInfo.MakeGenericMethod(methodType);
return genericMethodInfo;
}
请注意,我没有为 Expression<Func<TClass,TMethod>>
参数创建通用类型。
当您创建 genericClassType
并对其调用 GetMethod
时,CLR 尚不知道 TMethod
是什么类型。这只有在您在 methodInfo
上调用 MakeGenericType
时才会知道。因此,如果您使用完全参数化的 Expression<Func<TClass,TMethod>>
类型调用 GetMethod
,它将找不到该方法。
这就是为什么您需要在没有参数类型的情况下调用 genericClassType.GetMethod("MyMethod")
并且如果方法重载则可能必须对其进行过滤。之后您可以调用 MakeGenericMethod(methodType)
并获得完全参数化的 methodInfo 对象。
我相信您问题的答案是 "There is no way to do this"。
由于 GetMethod 在进行查找时无法 "MakeGenericMethod",您有一个方法具有一个已知的通用参数 (TClass) 和一个未知的通用参数 (TMethod)。当部分参数已知但不是全部参数已知时,反射无法查找方法。
注意 - 即使您 知道 TMethod 应该是什么("int" 在您的示例中),这将需要 "MakeGenericMethod" 我在上一段中提到。
在下面的代码中,我应该如何设置变量 "paramType" 以便它与 GetMethod() 调用中显示的方法匹配?
下面的代码与示例中的方法不匹配 class(methodInfo 为空)。
using System;
using System.Linq.Expressions;
public class MyClass<TClass>
{
public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
{
}
}
class Program
{
static void Main( string[] args )
{
var classType = typeof( MyClass<> );
// What should this really be?
var paramType = typeof( Expression<> ).MakeGenericType( typeof( Func<,> ) );
var methodInfo = classType.GetMethod( "MyMethod", new Type[] { paramType } );
}
}
编辑:我知道如何使用 GetMethods
或其他某种形式的迭代/假设来获得 MethodInfo
。我的问题具体是关于如何设置 paramType
的 System.Type
,如果它甚至可以为它生成 System.Type
。
编辑 2:为了更具体地解决问题,我更新了代码以增加风味:
using System;
using System.Linq.Expressions;
public class MyClass<TClass>
{
public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
{
Console.WriteLine( "Type: {0} Return: {1}", typeof( TClass ).Name, typeof( TMethod ).Name );
}
public void MyMethod<TMethod>( TMethod param )
{
}
}
class Program
{
public int MyProperty { get; set; }
static void Main( string[] args )
{
var classType = typeof( MyClass<> );
var typeClass = typeof( Program );
var typeMethod = typeof( int );
// What should this really be?
var paramType = typeof( Expression<> )
.MakeGenericType( typeof( Func<,> )
.MakeGenericType( typeClass, typeMethod )
);
var methodInfo = classType
.MakeGenericType( typeClass )
.GetMethod( "MyMethod", new Type[] { paramType } );
}
}
这也不起作用 - 这个包含更多信息的不同版本的 paramType
似乎不匹配。
在非一般情况下,有人可能想这样调用"MyMethod":
// I want to use a MethodInfo to perform this function:
new MyClass<Program>().MyMethod( _program => _program.MyProperty );
为此,您需要了解泛型类型,否则我认为您的任务将无法完成。
如果您的目的是在泛型 class 知道其任何类型之前为泛型创建一个泛型 methodinfo,以便您稍后可以调用 MakeGenericType
并使用您的两种类型,那将获胜不可能。
这可以通过调用 typeof(MyClass<>).GetMethod("MyMethod")
来显示,这将 return null。
另一方面,如果您知道具体类型,那很容易:
static MethodInfo GetMethod(Type classType, Type methodType)
{
var genericClassType = typeof(MyClass<>).MakeGenericType(classType);
var methodInfo = genericClassType.GetMethod("MyMethod");
var genericMethodInfo = methodInfo.MakeGenericMethod(methodType);
return genericMethodInfo;
}
请注意,我没有为 Expression<Func<TClass,TMethod>>
参数创建通用类型。
当您创建 genericClassType
并对其调用 GetMethod
时,CLR 尚不知道 TMethod
是什么类型。这只有在您在 methodInfo
上调用 MakeGenericType
时才会知道。因此,如果您使用完全参数化的 Expression<Func<TClass,TMethod>>
类型调用 GetMethod
,它将找不到该方法。
这就是为什么您需要在没有参数类型的情况下调用 genericClassType.GetMethod("MyMethod")
并且如果方法重载则可能必须对其进行过滤。之后您可以调用 MakeGenericMethod(methodType)
并获得完全参数化的 methodInfo 对象。
我相信您问题的答案是 "There is no way to do this"。
由于 GetMethod 在进行查找时无法 "MakeGenericMethod",您有一个方法具有一个已知的通用参数 (TClass) 和一个未知的通用参数 (TMethod)。当部分参数已知但不是全部参数已知时,反射无法查找方法。
注意 - 即使您 知道 TMethod 应该是什么("int" 在您的示例中),这将需要 "MakeGenericMethod" 我在上一段中提到。