我正在创建一个通用接口(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 的回答中使用了该方法并且它工作正常,特别是如果您可以在基类中隐藏从 IVisitableObject
到 T
的转换。但是如果你想避免强制类实现非泛型接口(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/