通用接口和类型分析

时间:2012-04-28 03:16:42

标签: c# generics collections types interface

我试图在通过接口通信的几个类之间传递消息。但是,由于我希望尽可能通用,我遇到了问题,因为传入消息的消息类型可能与传出类型不同。我粘贴了一些代码以使其更清晰。

下面的代码无法编译,因为接口实现传递的类型不同于阻塞集合的类型,它应该添加传入消息。我希望能够发送可能与传入类型不同的类型(传入类型显然总是与阻塞集合中的元素类型匹配)。我可以以某种方式绕过任何类型的转换或解析,即使这意味着我需要重新设计我的界面或类吗?

当涉及到使用接口并且遇到递归,堆栈溢出错误等问题时,我仍然很新鲜。所以,如果你有什么建议我可以改进设计明智或只是快速修复,那么请帮助我学习。我非常渴望了解如何实现更好的模式。

由于

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]
    }
}

1 个答案:

答案 0 :(得分:1)

我很难在这里理解你的目标,但也许MessagePassing<U>(U message)应该是MessagePassing(U message)interface IClientMessaging应该是interface IClientMessaging<U>

然后InProcessMessaging<T, U> : IClientMessaging<U> - 但我不明白为什么InProcessMessaging实施IClientMessaging并管理IClientMessaging的订阅者列表。在我看来,一个类将管理订阅者,另一个类是订阅者(IClientMessaging)。

您说UT是不同的类型。嗯 - 他们有关系吗?另一个是一个包装?听起来像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),在您的实施中可以确保objectTConsumed之前是{{1}}。

否则,您可以通过C#事件创建直接的客户端到客户端链接,但您似乎打算使用中央调度程序。中央调度员需要跟踪这些不同的和无限数量的类型,这些类型要么需要反射,要么不知道传递的类型(如前一段所述)

你应该看一下Reactive Extensions和观察者模式的想法。

我删除了我的评论,因为它过于繁琐。