【问题标题】:Creating a Messenger service创建 Messenger 服务
【发布时间】:2015-03-26 10:40:38
【问题描述】:

为了帮助减少我的 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 类负责接收对消息的订阅,订阅者必须指定他们将收到的预期有效负载的返回类型,以及他们正在订阅的消息字符串。

subscribe 方法处理订阅,send 方法将调用Callback 属性并将有效负载发送给任何订阅者。

我遇到的问题是Action&lt;T&gt; 是一个委托并且没有基本继承。我不能简单地将泛型添加到Subscription 结构,因为这会使List&lt;Subscription&gt; 成为List&lt;Subscription&lt;T&gt;&gt;,这会搞砸。

需要注意的一点是,我将来也将允许订阅没有有效负载。我正在努力思考如何实现这一目标。

编辑 使用马特的代码,我已经对其进行了调整以满足我的要求。如果有人感兴趣,就在这里。

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);
    }
}

【问题讨论】:

    标签: c# generics delegates action


    【解决方案1】:

    解决此问题的最佳方法是使用具有通用方法的接口为您执行操作。

    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;
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-20
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多