我正在创建一个通用接口(interface)作为命令模式工作:

public interface IGenericComponent<T> where T : IVisitableObject
{
    void Update(T msg);
}

然后,我将拥有另一个类,我将拥有该接口(interface)的一堆实现(每个实现都有自己的类型)。在那里,我将有一个字典来放置要执行的命令列表,如下所示:
private Dictionary<MessageType, List<IGenericComponent>> _components;

这会产生编译错误,因为我没有为 IGenericComponent 放置类型。我有一个线程调用 Update 方法和一个订阅方法(将组件插入字典):
public void Subscribe<T>(MessageType messageType, IGenericComponent<T> component) where T : IVisitableObject, new()
    {
        lock (_monitorDictionary)
        {
            List<IGenericComponent> subscribedList;
            if (_components.TryGetValue(messageType, out subscribedList))
            {
                subscribedList.Add(component);
                IVisitableObject firstUpdate;
                if(_messageBuffer.TryGetValue(messageType, out firstUpdate))
                    component.Update((T)firstUpdate);
            }
            else
            {
                subscribedList = new List<IGenericComponent>();
                subscribedList.Add(component);
                _components[messageType] = subscribedList;
            }
        }
    }

    private void ProcessQueue()
    {
        while (true)
        {
            IVisitableObject msg;
            lock (_monitorQueue)
            {
                msg = _queue.Dequeue();
            }
            List<IGenericComponent> components;
            lock(_monitorDictionary)
            {
                components = _components[msg.MsgType];
            }
            if(components!= null)
            {
                foreach (IGenericComponent genericComponent in components)
                    genericComponent.Update(msg);
            }
        }
    }

这段代码不能编译...
我来自 Java 编程,在 Java 中,我可以在实例化类型时省略参数化类型。所以......我想知道是否有可能在 C# 中做到这一点,所以它会假设它的泛型类型(IVisitableObject)。或者,如果您知道解决此问题的更好方法...
我解决这个问题的方式不是我想使用的方式。我已经从接口(interface)中删除了泛型,并使用了泛型类型 IVisitableObject 作为 Update 方法的参数。
提前致谢。

最佳答案

我在 Jason 的回答中使用了该方法并且它工作正常,特别是如果您可以在基类中隐藏从 IVisitableObjectT 的转换。但是如果你想避免强制类实现非泛型接口(interface),你可以使用这种模式。将您的订阅者存储为 List<object> 并使用辅助类 ( Dispatcher ) 发送消息。

public interface IVisitableObject { }
public interface IGenericComponent<T> where T : IVisitableObject
{
    void Update(T msg);
}

abstract class Dispatcher
{
    protected Dispatcher() { }

    public abstract void Dispatch(IVisitableObject message, IEnumerable<object> subscribers);


    static Dictionary<Type, Dispatcher> dispatchers = new Dictionary<Type, Dispatcher>();

    static Dispatcher GetDispatcherFor(IVisitableObject message)
    {
        Type type = message.GetType();

        if (!dispatchers.ContainsKey(type))
        {
            Type closedType = typeof(Dispatcher<>).MakeGenericType(message.GetType());
            object dispatcher = Activator.CreateInstance(closedType);
            dispatchers[type] = (Dispatcher)dispatcher;
        }

        return dispatchers[type];
    }
}

class Dispatcher<T> : Dispatcher where T : IVisitableObject
{
    public override void Dispatch(IVisitableObject message, IEnumerable<object> subscribers)
    {
        var msg = (T)message;
        foreach (var subscriber in subscribers.OfType<IGenericComponent<T>>())
        {
            subscriber.Update(msg);
        }
    }
}

关于接口(interface)上的 C# 泛型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8807069/

10-17 00:45