接口上的C#泛型

接口上的C#泛型,c#,generics,C#,Generics,我正在创建一个通用接口,用作命令模式: public interface IGenericComponent<T> where T : IVisitableObject { void Update(T msg); } 公共接口IGenericComponent,其中T:IVisitableObject { 无效更新(T msg); } 然后,我将有另一个类,我将持有这个接口的一系列实现(每个都有自己的类型)。在那里,我将有一个字典来列出要执行的命令列表,如下所示: pri

我正在创建一个通用接口,用作命令模式:

public interface IGenericComponent<T> where T : IVisitableObject
{
    void Update(T msg);
}
公共接口IGenericComponent,其中T:IVisitableObject
{
无效更新(T msg);
}
然后,我将有另一个类,我将持有这个接口的一系列实现(每个都有自己的类型)。在那里,我将有一个字典来列出要执行的命令列表,如下所示:

private Dictionary<MessageType, List<IGenericComponent>> _components;
private Dictionary\u组件;
这会生成编译错误,因为我没有为IGenericComponent输入类型。我有一个线程调用Update方法和一个订阅方法(在字典中插入一个组件):

public void Subscribe(MessageType MessageType,IGenericComponent组件),其中T:IVisitableObject,new()
{
锁(监视器字典)
{
列表订阅列表;
if(_components.TryGetValue(messageType,out subscribedList))
{
subscribedList.Add(组件);
ivisitableobjectfirstupdate;
if(_messageBuffer.TryGetValue(messageType,out firstUpdate))
组件更新((T)首次更新);
}
其他的
{
subscribedList=新列表();
subscribedList.Add(组件);
_组件[messageType]=订阅列表;
}
}
}
私有void ProcessQueue()
{
while(true)
{
ivisitableobjectmsg;
锁
{
msg=_queue.Dequeue();
}
列出组件;
锁(监视器字典)
{
组件=_组件[msg.MsgType];
}
if(组件!=null)
{
foreach(IGenericComponent通用组件中的组件)
genericComponent.Update(msg);
}
}
}
此代码不编译。。。 我来自Java编程,在Java中,我可以在实例化类型时操作参数化类型。所以我想知道是否有可能在C#中实现这一点,因此它会假设它是泛型类型(IVisitableObject)。或者如果你知道解决这个问题的更好方法。。。 我解决这个问题的方法不是我想用的方法。我已经从接口中删除了泛型,并使用泛型类型IVisitableObject作为Update方法的参数。
提前谢谢。

最简单的解决办法是

interface IGenericComponent {
    void Update(IVisitableObject msg);
}
interface IGenericComponent<T> : IGenericComponent where T : IVisitableObject {
    void Update(T msg);
}
接口IGenericComponent{ 无效更新(IVisitableObject消息); } 接口IGenericComponent:IGenericComponent,其中T:IVisitableObject{ 无效更新(T msg); }
我在Jason的回答中使用了这种方法,效果很好,特别是如果您可以在基类中将强制转换从
IVisitableObject
隐藏到
T
。但是,如果希望避免强制类实现非泛型接口,可以使用此模式。将订阅服务器存储为
列表
,并使用帮助器类(
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);
        }
    }
}
公共接口IVisitableObject{}
公共接口IGenericComponent,其中T:IVisitableObject
{
无效更新(T msg);
}
抽象类调度器
{
受保护的调度程序(){}
公共抽象无效分派(IVisitableObject消息,IEnumerable订户);
静态字典分派器=新字典();
静态调度程序GetDispatcherFor(IVisitableObject消息)
{
Type Type=message.GetType();
如果(!dispatchers.ContainsKey(类型))
{
Type closedType=typeof(Dispatcher).MakeGenericType(message.GetType());
object dispatcher=Activator.CreateInstance(closedType);
调度员[类型]=(调度员)调度员;
}
返回调度员[类型];
}
}
类调度程序:调度程序,其中T:IVisitableObject
{
公共覆盖无效分派(IVisitableObject消息,IEnumerable订阅服务器)
{
var msg=(T)消息;
foreach(订阅服务器中的var订阅服务器。OfType())
{
订户更新(msg);
}
}
}

Java的泛型与.NET完全不同。在Java中,泛型相当于一点元数据和一些编译器代码,用于在编译时检查类型安全性,必要时发出类型转换(“擦除”)。然而,在.NET中,每个泛型类型在运行时构建为自己的类型;它们就像您使用特定类型编写代码一样,这就是为什么它们也适用于值类型和原语(例如,
字典
等,不包含键或值)。@Jason第一个建议是我现在使用的建议,但如果可能的话,我希望使用泛型。secong一个不能编译,你需要同时使用这两个。哦。。。对不起,我没意识到这个办法几乎解决了我的问题。问题是,我必须在继承自IgenericComponentNope的类中实现这两种更新方法,如果您定义了一个抽象类
抽象类GenericComponent:IGenericComponent,其中T:IVisitableObject{public abstract void update(T msg);public void update,则可以只实现泛型版本(IVisitableObject msg){this.Update((T)msg);}}
然后从该类派生!现在您只需要重写
GenericComponent.Update(T msg)
。工作得很好!非常感谢您和@Jason:)哦,我应该这样称呼它:Dispatcher.GetDispatcherFor(msg).Dispatch(msg,components);正确的?
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);
        }
    }
}