C# 使用反射调用带约束的泛型方法
我使用反射从泛型方法检索methodInfo:C# 使用反射调用带约束的泛型方法,c#,generics,reflection,constraints,C#,Generics,Reflection,Constraints,我使用反射从泛型方法检索methodInfo: public abstract class BaseIdea {} public class ModuleBaseLogic { public void Sponsor<T>(int id) { // Do something } } public class Caller { protected static MethodInfo GetMethod<T>(Expression<Act
public abstract class BaseIdea {}
public class ModuleBaseLogic {
public void Sponsor<T>(int id) {
// Do something
}
}
public class Caller {
protected static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
{
return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
}
public Caller() {
MethodInfo method = GetMethod<ModuleBaseLogic>(q => q.Sponsor<object>(id));
}
}
公共抽象类BaseIdea{}
公共类模块逻辑{
公共无效赞助商(int id){
//做点什么
}
}
公共类调用者{
受保护的静态MethodInfo GetMethod(表达式表达式表达式)
{
return((MethodCallExpression)expr.Body.Method.GetGenericMethodDefinition();
}
公共调用方(){
MethodInfo method=GetMethod(q=>q.赞助商(id));
}
}
这个很好用。但是,如果该方法具有以下约束:
public void Sponsor<T>(int id) where T : BaseIdea, new() {
// Do something
}
public void赞助商(int id),其中T:BaseIdea,new(){
//做点什么
}
q.赞助商
(调用方内部)未编译:
类型“object”不能用作泛型中的类型参数“T”
类型或方法“ModuleBaseLogic.赞助人(int)”没有隐式
从“object”到“BaseIdea”的引用转换
我试着用
q.shandor
替换它,但这也不起作用这里有一些例子,如果你有一个其中t:SomeClass,new()
公共抽象类MyBaseClass{}
公共类MyClass:MyBaseClass{}
公共类MyClass2:MyBaseClass
{
公共MyClass2(int x)
{
}
}
公共类SomeOtherClass{}
公共静态void MyMethod(),其中T:MyBaseClass,new(){}
公共静态void Main(字符串[]args)
{
MyMethod();//不起作用,因为MyBaseClass是抽象的
MyMethod();//之所以有效,是因为T是MyClass,它是从MyBaseClass派生的
MyMethod();//不起作用,因为它没有标准构造函数“MyClass2()”它有一个参数为“MyClass2(int x)”的构造函数
MyMethod();//不起作用,因为t是另一个类,并且它不是从MyBaseClass派生的。
}
到目前为止,这应该是可行的:
public abstract class BaseIdea {}
public class ConcreteIdea : BaseIdea {}
public class ModuleBaseLogic {
public void Sponsor<T>(int id)
where T : BaseIdea, new()
{
// Do something
}
}
public class Caller {
protected static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
{
return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
}
public Caller() {
int id = 1;
MethodInfo method = GetMethod<ModuleBaseLogic>(q => q.Sponsor<ConcreteIdea>(id));
}
}
公共抽象类BaseIdea{}
公共类ConcreteIdea:BaseIdea{}
公共类模块逻辑{
公共无效赞助商(int id)
其中T:BaseIdea,new()
{
//做点什么
}
}
公共类调用者{
受保护的静态MethodInfo GetMethod(表达式表达式表达式)
{
return((MethodCallExpression)expr.Body.Method.GetGenericMethodDefinition();
}
公共调用方(){
int-id=1;
MethodInfo method=GetMethod(q=>q.赞助商(id));
}
}
给一点解释:
像Jon Skeet提到的对象不能是任何具有任何泛型约束的方法的泛型参数。
BaseIdea不能是泛型参数,因为它是抽象的,基类通常需要抽象。
最简单的可能参数是一个具体的类,它派生自BaseIdea,它与我的ConcreteIdea类一起给出。
正如kara提到的,新的()约束还需要一个无参数构造函数,也可以是隐式构造函数(默认构造函数)。另一种方法是使用一个表达式,通过使用
nameof()
操作符确定方法的名称,然后实际执行该表达式
public class Caller
{
protected static MethodInfo GetMethod<T>(Expression<Func<T, string>> expr) where T: class
{
// Execute the expression. We will get the method name.
string methodName = expr.Compile()(null);
// Return generic method information by name of the method
return typeof(T).GetMethod(methodName);
}
public Caller()
{
MethodInfo method = GetMethod<ModuleBaseLogic>(m => nameof(m.Sponsor));
}
}
公共类调用者
{
受保护的静态MethodInfo GetMethod(表达式expr),其中T:class
{
//执行表达式。我们将获得方法名称。
string methodName=expr.Compile()(空);
//按方法名称返回泛型方法信息
返回typeof(T).GetMethod(methodName);
}
公共呼叫者()
{
MethodInfo method=GetMethod(m=>nameof(m.赞助商));
}
}
注意:当有多个使用相同名称的方法重载时,这将不起作用。我希望
q.shandor
能起作用-您在尝试时看到了什么问题?(考虑到对象
不满足约束条件,您在q.赞助商
中遇到的错误是完全可以理解的。)“'BaseIdea'必须是带有公共无参数构造函数的非抽象类型,才能用作参数't'”它是抽象的(并且必须是)您的泛型类型约束是t:BaseIdea,new()
,这意味着T
必须是从BaseIdea
派生的类型,该类型不是抽象的,并且具有公共无参数构造函数。通过的类型必须满足所有这些条件。我怀疑BaseIdea
本身是抽象的,或者它没有公共的无参数构造函数。这很简单,当您编写调用泛型方法的代码时,必须传递满足所有泛型类型约束的类型。Thx。我没有提供“BaseIdea”是抽象的信息。对不起。我添加了另一个派生自“BaseIdea”的类,并将其用作泛型类型参数谢谢您的回答。我自由地修改它以匹配我的问题。(这是我的错,问题中缺少了“摘要”,而不是你的。但是其他可能在这里结束的人应该得到我问题的正确答案)
public class Caller
{
protected static MethodInfo GetMethod<T>(Expression<Func<T, string>> expr) where T: class
{
// Execute the expression. We will get the method name.
string methodName = expr.Compile()(null);
// Return generic method information by name of the method
return typeof(T).GetMethod(methodName);
}
public Caller()
{
MethodInfo method = GetMethod<ModuleBaseLogic>(m => nameof(m.Sponsor));
}
}