C# 动作代理的协方差和逆变
我被卡住了,为什么这不起作用:C# 动作代理的协方差和逆变,c#,C#,我被卡住了,为什么这不起作用: var childAction = new Action<CancelCommand>(blabla); Action<IDomainCommand> upperAction = (Action<IDomainCommand>) childAction; var childAction=新操作(blabla); Action upperAction=(Action)childAction; 如果CancelComma
var childAction = new Action<CancelCommand>(blabla);
Action<IDomainCommand> upperAction = (Action<IDomainCommand>) childAction;
var childAction=新操作(blabla);
Action upperAction=(Action)childAction;
如果CancelCommand实现IDOMAIN命令,为什么不起作用?
顺便问一下:我在这里想做的是协变还是逆变
先谢谢你
最好的
劳林
编辑
谢谢你们的快速回复
我之所以需要它,是因为我构造了一个通用的操作模板。
我有以下界面:
IMessageBus.RegisterAction<T>(Action<T> registerAction) where T : IDomainCommand
IMessageBus.RegisterAction(Action RegisterAction),其中T:IDOMain命令
因为我必须在运行时构建此操作,所以我的代码如下所示:
var genericExecuteAction = this.GetType().GetMethod("ExecuteCommandAction",
BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(commandType);
var actionType = typeof(Action<>).MakeGenericType(commandType);
var @delegate = Delegate.CreateDelegate(actionType, this, genericExecuteAction);
var actionDelegate = (Action<DomainCommandBase>)@delegate;
messageBus.Register(actionDelegate);
var genericExecuteAction=this.GetType().GetMethod(“ExecuteCommandAction”,
BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(commandType);
var actionType=typeof(Action).MakeGenericType(commandType);
var@delegate=delegate.CreateDelegate(actionType,this,genericExecuteAction);
var actionDelegate=(Action)@delegate;
messageBus.Register(actionDelegate);
问题是我需要强制转换它,以便将其传递给此方法。
看到了吗?
我们使用的mesasge总线背后是RX,不幸的是,所有的方法都使用泛型,现在出现了非泛型重载。Action的类型参数是反变的:您可以将
Action
分配给Action
,因为显然可以处理任何对象的方法也可以处理字符串
您在这里所做的是尝试将在
CancelCommand
(派生类型)上工作的方法作为在任何IDomainCommand
(基本类型)上工作的方法计费。这在逻辑上是错误的,因此编译器不允许您这样做——如果它允许,您可以调用upperAction
向其传递不同类型的域命令
,这是相反的。这不起作用,因为如果可能的话,您可以这样写:
interface IDomainCommand { }
class CancelCommand : IDomainCommand { }
class AcceptCommand : IDomainCommand { }
Action<CancelCommand> a1 = c => { };
Action<IDomainCommand> a2 = a1;
var acceptCommand = new AcceptCommand();
a2(acceptCommand); // what???
接口IDOMAIN命令{}
类CancelCommand:IDomainCommand{}
类AcceptCommand:IDomainCommand{}
动作a1=c=>{};
动作a2=a1;
var acceptCommand=new acceptCommand();
a2(接受命令);//什么???
a2
指向a1
,a1不能接受AcceptCommand
参数,因为它不是CancelCommand
等等,为什么要这样做
您的childAction
是一种接受CancelCommand
并对其执行操作的功能
但是upperAction
可以在任何idomain命令
上调用,而不仅仅是取消命令
。假设上述条件成立;当我这样做的时候会发生什么
upperAction(new EditCommand());
其中类EditCommand:IDomainCommand
如果您尝试以另一种方式分配任务:
var upperAction = new Action<IDomainCommand>(idc => { });
Action<CancelCommand> childAction = upperAction;
var upperAction=新操作(idc=>{});
Action childAction=upperAction;
它很有效,你甚至不需要演员阵容。任何
操作
都算作操作
您忘记了如何使用这些代理
var childAction = new Action<CancelCommand>(blabla);
Action<IDomainCommand> upperAction = (Action<IDomainCommand>) childAction;
var childAction=新操作(blabla);
Action upperAction=(Action)childAction;
意味着
upperAction
将在将来的某个时候被调用,传递某种形式的IDomainCommand
对象。您赋予它一个只能处理CancelCommand
对象的函数。但是(可能)还有其他类实现了IDomainCommand
,并且upperAction
可以与它们中的任何一个一起调用。Co-&Contra-variance只在接口上起作用,不是委托。@Enigmativity:它也适用于委托。谢谢。我找到了答案:我只需要调用Register方法over reflection=)谢谢你们的快速回答。我通过编辑我的初始问题来回答你的问题。