C# 将具有泛型方法的接口实例转换为操作
我正在努力使用我可以使用反射检索的C# 将具有泛型方法的接口实例转换为操作,c#,generics,reflection,delegates,action,C#,Generics,Reflection,Delegates,Action,我正在努力使用我可以使用反射检索的MethodInfo创建Action的实例 使用下面的示例,我可以轻松地对对象调用自定义方法,但我确实希望将它们转换为操作 我尝试过使用Delegate.CreateDelegate来执行此操作,但我似乎无法让它返回具有泛型类型的操作 示例 我创建了以下界面: interface IMyTest { } // Marker interface interface<TInput> IMyTest : IMyTest { void MyMetho
MethodInfo
创建Action
的实例
使用下面的示例,我可以轻松地对对象调用自定义方法,但我确实希望将它们转换为操作
我尝试过使用Delegate.CreateDelegate
来执行此操作,但我似乎无法让它返回具有泛型类型的操作
示例
我创建了以下界面:
interface IMyTest { } // Marker interface
interface<TInput> IMyTest : IMyTest {
void MyMethod(TInput input);
}
我想要的
在DoCallMyMethod
内部,我希望将MethodInfo方法
转换为通用的操作
,结果如下:
Action<type> myAction = method;
MyClass foo = new MyClass();
var action1 = DoCallMyMethod<DateTime>(foo);
var action2 = DoCallMyMethod<int>(foo);
action1(DateTime.Now);
action2(47);
Action myAction=method;
但这显然不起作用
我发现了一些类似的SO帖子(但没有一篇完全涵盖我的情况),最终得到了类似的答案:
Action<object> action =
(Action<object>)Delegate.CreateDelegate(typeof(Action<object>), target, method);
动作动作=
(Action)Delegate.CreateDelegate(类型(Action)、目标、方法);
但这不起作用,因为“无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明性不兼容。”
如何获取指定的
类型为其输入类型的操作,同时仍保留对象引用(没有出现新实例)?您无法从MyMethod
中的一个创建操作,因为该方法需要特定对象的类型(int
,DateTime
)如果将其视为操作
,则可以使用任何类型的对象调用它
由于您需要的是返回一个操作
,因此不需要将输入值传递给DoCallMyMethod
方法。可以将输入类型作为泛型参数传递:
public Action<T> DoCallMyMethod<T>(object target)
{
var @interface = typeof(IMyTest<T>);
if (@interface.IsAssignableFrom(target.GetType()))
{
var method = @interface.GetMethod("MyMethod");
if (method != null)
{
var action = Delegate.CreateDelegate(typeof(Action<T>), target, method) as Action<T>;
return action;
}
}
return null;
}
public Action DoCallMyMethod(对象目标)
{
var@interface=typeof(IMyTest);
if(@interface.IsAssignableFrom(target.GetType()))
{
var method=@interface.GetMethod(“MyMethod”);
if(方法!=null)
{
var action=Delegate.CreateDelegate(typeof(action)、target、method)作为action;
返回动作;
}
}
返回null;
}
然后,像这样使用它:
Action<type> myAction = method;
MyClass foo = new MyClass();
var action1 = DoCallMyMethod<DateTime>(foo);
var action2 = DoCallMyMethod<int>(foo);
action1(DateTime.Now);
action2(47);
MyClass foo=newmyclass();
var action1=DoCallMyMethod(foo);
var action2=DoCallMyMethod(foo);
动作1(DateTime.Now);
行动2(47);
如果在编译时不知道输入的类型,可以尝试以下方法:
public Delegate DoCallMyMethod(object target, Type inputType)
{
var @interface = typeof(IMyTest<>).MakeGenericType(inputType);
if (@interface.IsAssignableFrom(target.GetType()))
{
var method = @interface.GetMethod("MyMethod");
if (method != null)
{
var @delegate = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(inputType), target, method);
return @delegate;
}
}
return null;
}
public委托DoCallMyMethod(对象目标,输入类型)
{
var@interface=typeof(IMyTest)。MakeGenericType(inputType);
if(@interface.IsAssignableFrom(target.GetType()))
{
var method=@interface.GetMethod(“MyMethod”);
if(方法!=null)
{
var@delegate=delegate.CreateDelegate(typeof(Action).MakeGenericType(inputType),目标,方法);
return@delegate;
}
}
返回null;
}
并像这样使用它:
MyClass foo = new MyClass();
var action1 = DoCallMyMethod(foo, typeof(DateTime)) as Action<DateTime>;
var action2 = DoCallMyMethod(foo, typeof(int)) as Action<int>;
action1(DateTime.Now);
action2(47);
//or
int input = 47;
var @delegate = DoCallMyMethod(foo, input.GetType());
@delegate.DynamicInvoke(input);
MyClass foo=newmyclass();
var action1=DoCallMyMethod(foo,typeof(DateTime))作为操作;
var action2=DoCallMyMethod(foo,typeof(int))作为Action;
动作1(DateTime.Now);
行动2(47);
//或
int输入=47;
var@delegate=DoCallMyMethod(foo,input.GetType());
@delegate.DynamicInvoke(输入);
但是,如果需要返回一个操作
,则可以执行一个操作,接收一个对象并在该对象的类型有效时调用该方法:
public Action<object> DoCallMyMethod(object target, Type inputType)
{
var @interface = typeof(IMyTest<>).MakeGenericType(inputType);
if (@interface.IsAssignableFrom(target.GetType()))
{
var method = @interface.GetMethod("MyMethod");
if (method != null)
{
Action<object> action = obj =>
{
if (obj.GetType().IsAssignableFrom(inputType))
method.Invoke(target, new object[] { obj });
};
return action;
}
}
return null;
}
public Action DoCallMyMethod(对象目标,输入类型)
{
var@interface=typeof(IMyTest)。MakeGenericType(inputType);
if(@interface.IsAssignableFrom(target.GetType()))
{
var method=@interface.GetMethod(“MyMethod”);
if(方法!=null)
{
Action=obj=>
{
if(obj.GetType().IsAssignableFrom(inputType))
调用(目标,新对象[]{obj});
};
返回动作;
}
}
返回null;
}
而且
MyClass foo = new MyClass();
Action<object> action = DoCallMyMethod(foo, typeof(int));
action(47); // MyMethod(int) is called.
action("..."); // Nothing happens.
MyClass foo=newmyclass();
Action-Action=DoCallMyMethod(foo,typeof(int));
行动(47);//调用MyMethod(int)。
行动(“…”);//什么也没发生。
现在,您有了一个操作
,它只在传递整数时调用MyMethod(int)
。它以某种方式工作,但我还需要一个步骤,我无法从您的答案中推断出来(从问题中可能还不清楚)。一旦我拥有了委托
,而不知道输入的类型,我如何从中获得通用操作?例如,如果我还有一个方法AddExternalCaller(Action callback)
,那么回调可以是MyMethod
的变体之一。然后,我如何让addernalcaller()
和DoCallMyMethod()
向列表的全局集合添加操作?@GTHvidsten:但是您不能将操作
之类的操作
或操作
添加到列表
,因为操作
不是操作
。当传递对象的方法需要int
时,不能调用该方法。事实上,这在另一个方向上是有效的,因为Action
是逆变的,您可以将Action
分配给Action
变量,您可以调用一个方法,该方法期望对象具有整数。我认为您需要更改保存回调的设计方式。以前我将Action
转换为Action
的一种方法是使用以下语法进行转换:void convert(Action callback){Action foo=input=>callback((T)input);}
。我能够将动态委托转换为如下操作:Action handler=request=>@delegate.DynamicInvoke(request)代码>。到目前为止,它在我的场景中也起作用。你觉得这有什么特别的缺点吗?@GTHvidsten如果
MyClass foo = new MyClass();
Action<object> action = DoCallMyMethod(foo, typeof(int));
action(47); // MyMethod(int) is called.
action("..."); // Nothing happens.