【发布时间】:2021-07-28 19:57:01
【问题描述】:
这是我的代码
IDevice接口用于声明类是MessageBus的设备。
public interface IDevice
{
int ID{ get;}
}
ISubscriber<> 用于声明该类是订阅者并订阅了TMessage。
public interface ISubscriber<TMessage> where TMessage : IMessage
{
void Listen(TMessage message);
}
IMessage 用于声明消息。
public interface IMessage { }
这里定义了一条消息和订阅该消息的设备
public class TestMessage : IMessage { }
public class TestDevice : IDevice, ISubscriber<TestMessage>
问题来了,如何将TestDevice 从IDevice 转换为ISubscriberList
public class MessageBus
{
//key: Type of message
public Dictionary<Type, List<ISubscriber<IMessage>>> SubscriberList { get; }
//...
public void Subscribe(IDevice device)
{
var deviceInfo = device.GetType();
var isSubscriber = deviceInfo.GetInterfaces().Any(item => item.IsGenericType &&
if (isSubscriber)
{
var subscriptionList = deviceInfo.GetInterfaces().Cast<Type>().ToList().FindAll(item => item.IsGenericType && item.GetGenericTypeDefinition() == typeof(ISubscriber<>));
foreach (var subscription in subscriptionList)
{
var message = subscription.GenericTypeArguments.First();
if (!SubscriberList.ContainsKey(message))
{
SubscriberList.Add(message, new List<ISubscriber<IMessage>>());
}
//Here is the problem come from, how to cast the device from IDevice into ISubscriber<TestMessage> or ISubScriber<message>
SubscriberList[message].Add(device);
}
}
}
//...
}
对不起,如果这是一个转储问题。
【问题讨论】:
-
您不能将
IDevice投射到不相关的接口ISubscriber<>。这两个接口没有继承关系。不过,您可以将TestDevice投射到任何接口。如果您希望所有设备都作为订阅者工作,您需要让IDevice继承自ISubscriber -
那么有没有一种方法可以将
IDevice转换为它的真实类,比如这里的TestDevice? -
真正的问题是,当你真正需要
ISubscriber<IMessage>时,为什么还要使用IDevice?如果您希望IDevice成为ISubscriber,为什么不让它从ISubscriber继承? -
我希望有其他接口,如
IClient,设备可以是IClient,但不是ISubscriber。 -
如果您将 ISubscriber 更改为
public interface ISubscriber<out TMessage> where TMessage : IMessage { void Listen(IMessage message); },您将能够将 TestDevice 分配或传递给任何期望ISubscriber<IMessage>的变量或参数。如果你试图将一个接口转换为一个不相关的接口,那你就错了