创建信使服务
Creating a Messenger service
为了帮助减少 ViewModel 之间的依赖性,我正在尝试创建自己的 Messenger 服务。
这是一些代码:
public struct Subscription
{
public Type Type { get; set; }
public string Message { get; set; }
//Error: Cannot implicitly convert type 'System.Action<TPayload>' to 'System.Action'
public Action Callback { get; set; }
}
public static class Messenger
{
private static List<Subscription> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<Subscription>();
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscription()
{
Type = typeof(TPayload),
Message = message,
Callback = callback
});
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Get all subscribers that match the message and payload type
IEnumerable<Subscription> subs = Subscribers.Where(x => x.Message == message && x.Type == typeof(TPayload));
//Invoke the callback and send the payload.
foreach (Subscription sub in subs)
sub.Callback.Invoke(payload);
}
}
下面是关于这里到底发生了什么的低调:
Messenger
class 负责接收消息的订阅,订阅者必须指定 return 他们将接收的预期有效载荷的类型,以及消息字符串他们正在订阅。
subscribe 方法处理订阅,send 方法将调用 Callback
属性 并将有效负载发送给任何订阅者。
我遇到的问题是 Action<T>
是一个委托并且没有基继承。我不能简单地向 Subscription
结构添加泛型,因为那样会使 List<Subscription>
成为 List<Subscription<T>>
,这会搞砸。
需要注意的一件事是,我将来也将允许订阅 没有 有效负载。我正在努力思考如何实现这一目标。
编辑
使用 Matt 的代码,我对其进行了调整以满足我的要求。有兴趣的可以看这里
public interface ISubscriber
{
string Message { get; set; }
void InvokeMethod(object args);
}
public class Subscriber : ISubscriber
{
public string Message { get; set; }
public Action Callback { get; set; }
public virtual void InvokeMethod(object args = null)
{
Callback.Invoke();
}
}
public class Subscriber<T> : Subscriber
{
new public Action<T> Callback { get; set; }
public override void InvokeMethod(object payload)
{
if (!(payload is T))
throw new ArgumentException(String.Concat("Payload is not of type: ", typeof(T).Name), "payload");
Callback.Invoke((T)payload);
}
}
public static class Messenger
{
private static List<ISubscriber> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<ISubscriber>();
}
public static void Subscribe(string message, Action callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscriber()
{
Message = message,
Callback = callback
});
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscriber<TPayload>()
{
Message = message,
Callback = callback
});
}
public static void Send(string message)
{
//Invoke the Callback for all subscribers
foreach (Subscriber sub in GetSubscribers(message))
sub.InvokeMethod();
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Invoke the TypedCallback for all subscribers
foreach (ISubscriber sub in GetSubscribers(message))
sub.InvokeMethod(payload);
}
private static IEnumerable<ISubscriber> GetSubscribers(string message)
{
//Get all subscribers by matching message.
return Subscribers.Where(x => x.Message == message);
}
}
解决此问题的最佳方法是使用具有通用方法的接口来为您执行操作。
public interface ISubscription
{
Type Type { get;}
String Message { get; set; }
void InvokeMethod(object args);
}
public class Subscription<T> : ISubscription
{
public Type Type { get { return typeof(T); } }
public string Message { get; set; }
public Action<T> TypedCallback { get; set; }
void ISubscription.InvokeMethod(object args)
{
if (!(args is T))
{
throw new ArgumentException(String.Concat("args is not type: ", typeof(T).Name), "args");
}
TypedCallback.Invoke((T)args);
}
}
public static class Messenger
{
private static List<ISubscription> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<ISubscription>();
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscription<TPayload>()
{
Message = message,
TypedCallback = callback
});
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Get all subscribers that match the message and payload type
IEnumerable<ISubscription> subs = Subscribers.Where(x => x.Message == message && x.Type == typeof(TPayload));
foreach (ISubscription sub in subs)
sub.InvokeMethod(payload);
}
}
然后可以这样使用
class Program
{
static void Main(string[] args)
{
Action<String> StringAction = new Action<string>((a) => WriteString(a));
Action<Int32> Int32Action = new Action<Int32>((a) => WriteString(a.ToString()));
Messenger.Subscribe<String>("Sub1", StringAction);
Messenger.Send<String>("Sub1", "I am a string");
Messenger.Subscribe<Int32>("Sub2", Int32Action);
Messenger.Send<Int32>("Sub2", 72);
Console.ReadLine();
}
private static String WriteString(String message)
{
Console.WriteLine(message);
return message;
}
}
为了帮助减少 ViewModel 之间的依赖性,我正在尝试创建自己的 Messenger 服务。
这是一些代码:
public struct Subscription
{
public Type Type { get; set; }
public string Message { get; set; }
//Error: Cannot implicitly convert type 'System.Action<TPayload>' to 'System.Action'
public Action Callback { get; set; }
}
public static class Messenger
{
private static List<Subscription> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<Subscription>();
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscription()
{
Type = typeof(TPayload),
Message = message,
Callback = callback
});
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Get all subscribers that match the message and payload type
IEnumerable<Subscription> subs = Subscribers.Where(x => x.Message == message && x.Type == typeof(TPayload));
//Invoke the callback and send the payload.
foreach (Subscription sub in subs)
sub.Callback.Invoke(payload);
}
}
下面是关于这里到底发生了什么的低调:
Messenger
class 负责接收消息的订阅,订阅者必须指定 return 他们将接收的预期有效载荷的类型,以及消息字符串他们正在订阅。
subscribe 方法处理订阅,send 方法将调用 Callback
属性 并将有效负载发送给任何订阅者。
我遇到的问题是 Action<T>
是一个委托并且没有基继承。我不能简单地向 Subscription
结构添加泛型,因为那样会使 List<Subscription>
成为 List<Subscription<T>>
,这会搞砸。
需要注意的一件事是,我将来也将允许订阅 没有 有效负载。我正在努力思考如何实现这一目标。
编辑 使用 Matt 的代码,我对其进行了调整以满足我的要求。有兴趣的可以看这里
public interface ISubscriber
{
string Message { get; set; }
void InvokeMethod(object args);
}
public class Subscriber : ISubscriber
{
public string Message { get; set; }
public Action Callback { get; set; }
public virtual void InvokeMethod(object args = null)
{
Callback.Invoke();
}
}
public class Subscriber<T> : Subscriber
{
new public Action<T> Callback { get; set; }
public override void InvokeMethod(object payload)
{
if (!(payload is T))
throw new ArgumentException(String.Concat("Payload is not of type: ", typeof(T).Name), "payload");
Callback.Invoke((T)payload);
}
}
public static class Messenger
{
private static List<ISubscriber> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<ISubscriber>();
}
public static void Subscribe(string message, Action callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscriber()
{
Message = message,
Callback = callback
});
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscriber<TPayload>()
{
Message = message,
Callback = callback
});
}
public static void Send(string message)
{
//Invoke the Callback for all subscribers
foreach (Subscriber sub in GetSubscribers(message))
sub.InvokeMethod();
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Invoke the TypedCallback for all subscribers
foreach (ISubscriber sub in GetSubscribers(message))
sub.InvokeMethod(payload);
}
private static IEnumerable<ISubscriber> GetSubscribers(string message)
{
//Get all subscribers by matching message.
return Subscribers.Where(x => x.Message == message);
}
}
解决此问题的最佳方法是使用具有通用方法的接口来为您执行操作。
public interface ISubscription
{
Type Type { get;}
String Message { get; set; }
void InvokeMethod(object args);
}
public class Subscription<T> : ISubscription
{
public Type Type { get { return typeof(T); } }
public string Message { get; set; }
public Action<T> TypedCallback { get; set; }
void ISubscription.InvokeMethod(object args)
{
if (!(args is T))
{
throw new ArgumentException(String.Concat("args is not type: ", typeof(T).Name), "args");
}
TypedCallback.Invoke((T)args);
}
}
public static class Messenger
{
private static List<ISubscription> Subscribers { get; set; }
static Messenger()
{
Subscribers = new List<ISubscription>();
}
public static void Subscribe<TPayload>(string message, Action<TPayload> callback)
{
//Add to the subscriber list
Subscribers.Add(new Subscription<TPayload>()
{
Message = message,
TypedCallback = callback
});
}
public static void Send<TPayload>(string message, TPayload payload)
{
//Get all subscribers that match the message and payload type
IEnumerable<ISubscription> subs = Subscribers.Where(x => x.Message == message && x.Type == typeof(TPayload));
foreach (ISubscription sub in subs)
sub.InvokeMethod(payload);
}
}
然后可以这样使用
class Program
{
static void Main(string[] args)
{
Action<String> StringAction = new Action<string>((a) => WriteString(a));
Action<Int32> Int32Action = new Action<Int32>((a) => WriteString(a.ToString()));
Messenger.Subscribe<String>("Sub1", StringAction);
Messenger.Send<String>("Sub1", "I am a string");
Messenger.Subscribe<Int32>("Sub2", Int32Action);
Messenger.Send<Int32>("Sub2", 72);
Console.ReadLine();
}
private static String WriteString(String message)
{
Console.WriteLine(message);
return message;
}
}