-1

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

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

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

谢谢

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

1 回答 1

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可以有一个which 可以在尝试处理它之前Consume(object message)确保它object是一个。TConsumed

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

您还应该查看Reactive Extensions和 Observer 模式的想法。

我删除了我的评论,因为它变得太健谈了。

于 2012-04-28T03:36:58.157 回答