[英]C# Generics on interface
我正在创建一个通用接口作为命令模式:
public interface IGenericComponent<T> where T : IVisitableObject
{
void Update(T msg);
}
然后,我将有另一个类,我将持有这个接口的一堆实现(每个都有自己的类型)。 在那里我会有一个字典来放置要执行的命令列表,如下所示:
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)。 或者,如果你知道一个更好的方法来解决这个问题......我解决这个问题的方式并不是我想要使用的方式。 我已从界面中删除了泛型,并使用泛型类型IVisitableObject作为Update方法的参数。 提前致谢。
最简单的解决方案就是说
interface IGenericComponent {
void Update(IVisitableObject msg);
}
interface IGenericComponent<T> : IGenericComponent where T : IVisitableObject {
void Update(T msg);
}
我已经在Jason的答案中使用了这种方法并且它工作正常,特别是如果你可以在基类中隐藏从IVisitableObject
到T
的转换。 但是,如果您想避免强制类实现非泛型接口,则可以使用此模式。 将订阅者存储为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);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.