接口上的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);
}
}
}