Pau*_*aul 6 c# generics mono messaging unity-game-engine
我正在尝试为Unity游戏实现我自己的消息传递系统.我有一个基本版本 - 一个非常简单的例子如下:
// Messaging class:
private Dictionary<Type, List<Func<Message, bool>>> listeners; // Set up by some other code.
public void AddListener<T>(Func<Message, bool> listener) where T : Message {
this.listeners[typeof(T)].Add(listener);
}
public void SendMessage<T>(T message) where T : Message {
foreach (Func<Message, bool> listener in this.listeners[typeof(T)]) {
listener(message);
}
}
// Some other class:
private void Start() {
messaging.AddListener<MyMessage>(this.MessageHandler); // Subscribe to messages of a certain type.
}
private bool MessageHandler(Message message) { // We receive the message as the Message base type...
MyMessage message2 = (MyMessage)message; // ...so we have to cast it to MyMessage.
// Handle the message.
}
Run Code Online (Sandbox Code Playgroud)
一切正常.我现在要做的是实现一些"魔术",以允许使用实际派生类型调用消息处理程序,如下所示:
private bool MessageHandler(MyMessage message) {
// Handle the message.
}
Run Code Online (Sandbox Code Playgroud)
这意味着跨数千个脚本的消息处理代码不需要费心将Message对象转换为正确的派生类型 - 它已经是该类型.它会更方便.我觉得这可能有可能以某种方式使用泛型,代表,表达树,协方差和/或逆变,但我只是没有得到它!
我一直在尝试很多不同的事情,觉得我越来越近,但我无法到达那里.这些是我能够提出的两个部分解决方案:
// Messaging class:
private Dictionary<Type, List<Delegate>> listeners; // Delegate instead of Func<Message, bool>.
public void AddListener<T>(Func<T, bool> listener) where T : Message { // Func<T, bool> instead of Func<Message, bool>.
this.listeners[typeof(T)].Add(listener);
}
public void SendMessage<T>(T message) where T : Message {
foreach (Delegate listener in this.listeners[typeof(T)]) {
listener.Method.Invoke(method.Target, new object[] { message }); // Partial solution 1.
((Func<T, bool>)listener)(message); // Partial solution 2.
}
}
Run Code Online (Sandbox Code Playgroud)
部分解决方案1工作正常,但它使用反射,考虑到性能,这不是一个真正的选择 - 这是一个游戏,消息系统将被大量使用.部分解决方案2有效,但只有T通用参数可用时才有效.消息传递系统还将具有它将处理的Message对象队列,并且T将不在那里可用.
有没有办法实现这个目标?我非常感谢任何人都可以提供的任何帮助!
最后要注意的是我使用Unity,它使用Mono - .NET 4不是一个选项,据我所知这个规则使用"动态".
如果我正确理解了您的问题,您希望有一些常用的方法来存储和调用消息处理程序,同时为每个处理程序提供特定的消息类型.
一种方法是使用基类型接口处理程序和泛型类型实现:
interface IMessageHandler
{
bool ProcessMessage(Message m);
}
class MessageHandler<T>: IMessageHandler where T:Message
{
Func<T, bool> handlerDelegate;
public MessageHandler(Func<T, bool> handlerDelegate)
{
this.handlerDelegate = handlerDelegate;
}
public bool ProcessMessage(Message m)
{
handlerDelegate((T)m);
}
}
Run Code Online (Sandbox Code Playgroud)
您的处理程序字典应该将IMessageHandler作为值保存,并在AddListener方法中创建MessageHandler并将其添加到处理程序字典中.像这样:
private Dictionary<Type, IMessageHandler> listeners;
public void AddListener<T>(Func<T, bool> listener) where T : Message
{
this.listeners[typeof(T)].Add(new MessageHandler<T>(listener));
}
public void SendMessage(Message message)
{
foreach (IMessageHandler listener in this.listeners[message.GetType()])
{
listener.ProcessMessage(message);
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您可以在没有泛型参数的情况下调用SendMessage,并在实际的处理程序方法中获取类型参数.
| 归档时间: |
|
| 查看次数: |
859 次 |
| 最近记录: |