Zer*_*tor 5 c# generics types casting
在IMyMessage.cs中
public interface IMyMessage
{
}
Run Code Online (Sandbox Code Playgroud)
在IMyMessageReceiver.cs中
public interface IMyMessageReceiver<T> where T: IMyMessage
{
void HandleMessage(T message);
void Subscribe();
}
Run Code Online (Sandbox Code Playgroud)
在MyMessagePublisher.cs中
public static class MyMessagePublisher
{
private static Dictionary<Type, List<IMyMessageReceiver<IMyMessage>>> _subscribers;
static MyMessagePublisher
{
_subscribers = new Dictionary<Type, List<IMyMessageReceiver<IMyMessage>>>();
}
public static function Subscribe<T>(IMyMessageReceiver<T> receiver) where T: IMyMessage
{
Type messageType = typeof (T);
List<IMyMessageReceiver<IMyMessage>> listeners;
if(!_subscribers.TryGetValue(messageType, out listeners))
{
// no list found, so create it
List<IMyMessageReceiver<T>> newListeners = new List<IMyMessageReceiver<T>>();
// ERROR HERE: Can't convert List<IMyMessageReceiver<T>> to List<IMyMessageReceiver<IMyMessage>>
_subscribers.add(messageType, newListeners);
}
// I would then find the right list and add the receiver it to it but haven't got this far
}
}
Run Code Online (Sandbox Code Playgroud)
所以我希望使用一堆"IMyMessages"和"IMyMessageReceivers"来传递消息.我之前做了一个硬编码的方法但是厌倦了100个不同的发布/订阅函数名称,所以我想我会把它完美地包装在泛型中.
我的问题是,在使用泛型时我无法使代码工作.即使我指定Type T将是IMyMessage,我也不能在任何需要IMyMessage的地方使用T. 也许我只是习惯了基础/扩展类,因为它可以很好地工作.我已经尝试了从铸造到真正通用的各种方法,但我总是遇到同样的问题.
好的,这就是我如何看待它的工作方式。由于您尝试以不受支持的方式使用协方差,因此您需要避免在某些地方使用泛型。但这样做不会失去任何类型安全性。
创建一个非泛型IMessageReceiver接口,以便不能使用泛型参数的类型可以使用它:
public interface IMyMessageReceiver
{
void HandleMessage(IMyMessage message);
void Subscribe();
}
public interface IMyMessageReceiver<in T> : IMyMessageReceiver
where T : IMyMessage
{
void HandleMessage(T message);
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,您可以创建一个基类来简化事情:
public abstract class MyMessageReceiverBase<T> : IMyMessageReceiver<T>
where T : IMyMessage
{
public abstract void HandleMessage(T message);
public void HandleMessage(IMyMessage message)
{
if (!(message is T))
throw new InvalidOperationException();
HandleMessage((T)message);
}
public abstract void Subscribe();
}
Run Code Online (Sandbox Code Playgroud)
然后您可以更改IMyMessageListeners为使用非泛型版本,因为它实际上并不需要泛型类型:
public interface IMyMessageListeners
{
void Add(IMyMessageReceiver receiver);
// I added this since I think this is how you're going to use it
void Send(IMyMessage message);
}
Run Code Online (Sandbox Code Playgroud)
这个类的具体内容是这样的:
public class MyMessageListeners : IMyMessageListeners
{
readonly List<IMyMessageReceiver> _list = new List<IMyMessageReceiver>();
public void Add(IMyMessageReceiver receiver)
{
_list.Add(receiver);
}
public void Send(IMyMessage message)
{
foreach (var listener in _list)
listener.HandleMessage(message);
}
}
Run Code Online (Sandbox Code Playgroud)
然后(最后),你的静态类将如下所示:
public static class MyMessagePublisher
{
static readonly Dictionary<Type, IMyMessageListeners> _subscribers = new Dictionary<Type, IMyMessageListeners>();
// I added this too, since I think this is how you intend to use it
public static void Publish<T>(T message) where T : IMyMessage
{
Type messageType = typeof(T);
IMyMessageListeners listeners;
if (_subscribers.TryGetValue(messageType, out listeners))
listeners.Send(message);
}
public static void Subscribe<T>(IMyMessageReceiver<T> receiver) where T : IMyMessage
{
Type messageType = typeof(T);
IMyMessageListeners listeners;
if (!_subscribers.TryGetValue(messageType, out listeners))
{
// no list found, so create it
listeners = new MyMessageListeners();
_subscribers.Add(messageType, listeners);
}
listeners.Add(receiver);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样使用静态类:
MyMessagePublisher.Subscribe(new FooMessageReceiver());
MyMessagePublisher.Publish(new FooMessage());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1446 次 |
| 最近记录: |