我正在尝试使用MessagePack获取简单的消息传递服务。
该服务应保留DateFormat
,以便查找如何处理"交易"带有特定信息。
基本上,我有:
dictionary<type, Action<T>>
我明白了:
private Dictionary<Type, Action<IMessage>> subActions;
public void Subscribe<TMessage>(Action<TMessage> action) where TMessage : IMessage
{
subActions.Add(typeof(TMessage), action);
}
如果不清楚;消息&#34;到达&#34;作为Argument 2: cannot convert from 'System.Action<TMessage>' to 'System.Action<GameServer.Messages.IMessage>'
包含&#34;类型代码&#34;。来自&#34; typecode&#34;我得到了byte[]
,而应然后能够查找相应的Type
。显然,Action
应该将Action
作为参数。
我似乎无法得出逻辑结论,为什么编译器会给我这个错误,尽管我怀疑它与TMessage
与Dictionary
不在同一个上下文中有关。 1}}。
提前致谢!
答案 0 :(得分:0)
让我们考虑一下这些方法:
public void MessageMethodInterface(IMessage arg)
{
}
public void MessageMethodClass(MyMessage arg)
{
}
其中MyMessage
是实现IMessage
接口的类。
现在让我们创建一个Action
并使用它们:
var action = new Action<IMessage>(MessageMethodInterface);
action(new SomeOtherMessage());
SomeOtherMessage
实施IMessage
。这会奏效。我们有Action
以IMessage
作为输入。由于SomeOtherMessage实现了IMessage,因此它可以编译并运行。
现在让我们创建另一个Action
:
var action2 = new Action<IMessage>(MessageMethodClass);
action(new SomeOtherMessage());
这不起作用:我们创建了一个Action
,它应该接受IMessage
类型的任何对象,但是我们为它分配了一个只能处理类型为MyMessage
类的输入的方法 - 因此我们用我们提供的方法缩小了行动的范围 - 它不会编译。
代码中发生的情况是方案2.您希望字典包含可以处理IMessage
的方法,但是您传递的方法只能处理特定类型。这不是类型安全的。即使一个类实现了接口,该方法本身也只处理特定类型,而不是该接口的每种类型。与使用MyMessage
和SomeOtherMessage
的示例相同。
这是Action
类型的逆转。
基类型的Action
可以分配派生类型的操作。这是类型安全的b / c只使用基类型的方法将知道如何处理派生类型。反之则不然。以object
作为输入的方法将处理string
。由于string
公开了object
的所有方法和属性。但不是相反。
答案 1 :(得分:0)
它不起作用,因为您想要进行如下分配:
Action<IMessage> dest = new Action<TMessage>(x => x.TMessageProp = 123);
所以,如果编译器允许它,你可以进一步编写:
dest(new TAnotherMessage());
因为TAnotherMessage
也实现了IMessage
。但它会导致异常,因为dest
只适用于TMessage
。阅读有关逆变的更多信息。
您可以保持类型安全和fix it safely,因为您知道类型,您可以通过字典键传递给特定操作:
public void Subscribe<TMessage>(Action<TMessage> action) where TMessage : IMessage
{
subActions.Add(typeof(TMessage), x => action((TMessage)x));
}