泛型接口和类型分析
本文关键字:类型 泛型接口 | 更新日期: 2023-09-27 18:32:26
我正在尝试在通过接口通信的几个类之间传递消息。但是,由于我喜欢尽可能通用,因此遇到了问题,因为传入消息的消息类型可能与传出类型不同。我粘贴了一些代码以使其更清晰。
下面的代码无法编译,因为接口实现传递的类型与它应该向其添加传入消息的阻塞集合的类型不同。我希望能够发送可能与传入类型不同的类型(传入类型显然总是与阻塞集合中的元素类型匹配)。我可以以某种方式绕过任何类型的转换或解析,即使这意味着我需要重新设计我的界面或类?
在使用接口方面,我仍然很新鲜,并且在递归、堆栈溢出错误等方面苦苦挣扎。因此,如果您有建议,我可以明智地改进设计或只是快速修复,请帮助我学习。我非常渴望了解如何实现更好的模式。
谢谢
public interface IClientMessaging
{
void MessagePassing<U>(U message);
}
public class InProcessMessaging<T> : IClientMessaging
{
private Dictionary<Type, List<IClientMessaging>> Subscriptions;
public BlockingCollection<T> MessageBuffer;
public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions)
{
//Setup Message Buffer
MessageBuffer = new BlockingCollection<T>();
//Subscribe
Type type = typeof(T);
if (subscriptions.Keys.Contains(type))
{
subscriptions[type].Add(this);
}
else
{
subscriptions.Add(type, new List<IClientMessaging>());
subscriptions[type].Add(this);
}
Subscriptions = subscriptions;
}
public void SendMessage<U>(U message)
{
//Send message to each subscribed Client
List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)];
foreach (IClientMessaging subscriber in typeSubscriptions)
{
subscriber.MessagePassing<U>(message);
}
}
public T ReceiveMessage()
{
return MessageBuffer.Take();
}
public bool ReceiveMessage(out T item)
{
return MessageBuffer.TryTake(out item);
}
//Interface Implementation
public void MessagePassing<U>(U message)
{
MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want
//to send messages of a different type than the receiving type]
}
}
我正在努力理解你在这里的目标,但也许MessagePassing<U>(U message)
应该MessagePassing(U message)
,interface IClientMessaging
应该interface IClientMessaging<U>
.
然后InProcessMessaging<T, U> : IClientMessaging<U>
- 但我不明白为什么InProcessMessaging
实施IClientMessaging
并管理IClientMessaging
的订阅者列表. 在我看来,一个类会管理订阅者,而另一个类是订阅者(IClientMessaging
)。
你说U
和T
是不同的类型。 好吧 - 它们相关吗? 一个包装器是另一个包装器吗?听起来也许U
要么是T
的包装器,要么是包含T
但添加额外信息的泛型类本身。 在这种情况下,void MessagePassing<T>(Wrapper<T> message);
更新
根据到目前为止的评论...
interface IClientMessage {}
interface IClientMessage<U> : IClientMessage { /* ... */ }
但将它们重命名为:
interface IConsumer {} // (Or ISubscriber?)
interface IConsumer<TConsumed> : IConsumer{ /* ... */ }
并添加:
interface IGenerator { }
interface IGenerator <TGenerated> : IGenerator {
event EventHandler<TGenerated> ItemGenerated;
}
然后:
class Manager
{
Dictionary<TConsumed, IConsumer> consumers = new ...
/* Code for attaching ItemGenerated event handlers to clients */
}
class MyClient : IGenerator<string>, IConsumer<Foo>, IConsumer<Bar>
{
event IGenerator<string>.ItemGenerated ...
void IConsumer<Foo>.Consume(...) ...
void IConsumer<Bar>.Consume(...) ...
}
是的,这将使用反射来调用IConsumer<TConsumed>.Consume()
。 或者,您可以省略泛型,只使用 object
作为您的类型。 更好的是,IClientMessage
可以有一个Consume(object message)
,在您的实现中可以确保object
在尝试处理它之前是一个TConsumed
。
否则,您可以通过 C# 事件创建直接的客户端到客户端链接,但您似乎打算使用中央调度程序。 中央调度员需要跟踪这些不同且无限数量的类型,这些类型要么需要反射,要么不知道正在传递的类型(如上一段所述)
您还应该查看响应式扩展和观察者模式以获取想法。
我删除了我的评论,因为它变得太健谈了。