如何订阅具有特定参数c#的事件?

时间:2014-05-03 12:19:53

标签: c# .net

我有一个枚举prior

我的每个脚本都有一个priority类型的属性prior。 (每个脚本都有自己的类)

我有一个数据提供者,可以每帧发送事件。

我希望脚本只能订阅一个参数,该参数的优先级等于脚本的参数。

例如,具有moderate优先级的脚本应仅接收具有moderate事件参数参数的事件

prior有太多成员为每个成员创建一个特殊事件参数类。

不幸的是:

a)我只知道如何订阅某种事件类型。

b)我不能为事件参数创建泛型类,因为枚举的元素不是类型

我该怎么做?


该项目目前看起来像这样:

public class TDefault:MonoBehaviour,IDefault
{ 

    public enum prior
    {
        none,
        ...,
        terminal
    };
    prior priority;
    public virtual void apply()//For override by scripts
    {

    }
    void Start()
    {
        //There should be adding a method which calls apply() when event_manager 
        //sends Event with a certain priority
    }
    public TDefault ()
    {
        if(essential==null)
        essential=new TEssential();
    }

}

public class TApplyEventParam : EventArgs 
{
    public TDefault.prior priority;
    public TApplyEventParam(TDefault.prior _priority)
    {
        priority=_priority;
    }
}

    public class event_manager : TDefault
    {
        //This has fixed type
        event EventHandler<TApplyEventParam> handler=new EventHandler<TApplyEventParam>();
        void Update () 
        {
            foreach (prior p in (prior[]) Enum.GetValues(typeof(prior)))
            {
                handler(this,new TApplyEventParam(p));
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

您正在处理的问题,如果我理解正确的话,您希望根据事件有效负载(priority内的TApplyEventParam值有条件地调用您的事件订阅})。这是您无法做到的事情,导致您必须过滤掉事件处理程序中的不需要的事件,如@Henk-Holterman提出的

另一种方法可能是跳过事件的使用并在数据提供者中维护自己的订阅者列表。 基于您在问题中使用的术语(不是代码示例),您可以执行以下操作:

using System;
using System.Collections.Generic;

namespace Example
{
    public enum Prior
    {
        None,
        Moderate,
        Terminal
    };

    public abstract class ScriptBase
    {
        public abstract Prior Prior { get; }

        public abstract void Apply();

        public void Start(DataProvider dataProvider)
        {
            dataProvider.Subscribe(Prior, Apply);
        }

        public void Stop(DataProvider dataProvider)
        {
            dataProvider.Unsubscribe(Prior, Apply);
        }
    }

    public class ScriptHandlingModerateEvents : ScriptBase
    {
        public override Prior Prior
        {
            get { return Example.Prior.Moderate; }
        }

        public override void Apply()
        {
            Console.WriteLine("Handling moderate event by " + GetType().Name);
        }
    }

    public class ScriptHandlingTerminalEvents : ScriptBase
    {
        public override Prior Prior
        {
            get { return Example.Prior.Terminal; }
        }

        public override void Apply()
        {
            Console.WriteLine("Handling terminal event by " + GetType().Name);
        }
    }

    public class DataProvider
    {
        private readonly Dictionary<Prior, List<Action>> _subscribersByPrior;

        public DataProvider()
        {
            _subscribersByPrior = new Dictionary<Prior, List<Action>>();

            foreach (Prior prior in (Prior[])Enum.GetValues(typeof(Prior)))
            {
                _subscribersByPrior.Add(prior, new List<Action>());
            }
        }

        public void Subscribe(Prior prior, Action action)
        {
            _subscribersByPrior[prior].Add(action);
        }

        public void Unsubscribe(Prior prior, Action action)
        {
            _subscribersByPrior[prior].Remove(action);
        }

        public void DoSomethingThatTriggersPriorEvents(int someValue)
        {
            Prior prior = someValue % 2 == 0 ? Prior.Moderate : Prior.Terminal;
            foreach (var subscriber in _subscribersByPrior[prior])
            {
                subscriber();
            }
        }
    }

    public static class Program
    {
        public static void Main()
        {
            DataProvider dataProvider = new DataProvider();

            var scriptHandlingModerateEvents = new ScriptHandlingModerateEvents();
            scriptHandlingModerateEvents.Start(dataProvider);

            var scriptHandlingTerminalEvents = new ScriptHandlingTerminalEvents();
            scriptHandlingTerminalEvents.Start(dataProvider);

            for (int i = 0; i < 10; i++)
            {
                dataProvider.DoSomethingThatTriggersPriorEvents(i);
            }

            scriptHandlingTerminalEvents.Stop(dataProvider);
            scriptHandlingModerateEvents.Stop(dataProvider);

            Console.WriteLine();
        }
    }
}

这种方式DataProvider不知道脚本,但如果这不是问题,您可以维护ScriptBase实例列表并检查其中的Prior属性 DoSomethingThatTriggersPriorEvents喜欢这样:

public class DataProvider2
{
    private readonly List<ScriptBase> _scripts = new List<ScriptBase>();

    public void Subscribe(ScriptBase script)
    {
        _scripts.Add(script);
    }

    public void Unsubscribe(ScriptBase script)
    {
        _scripts.Remove(script);
    }

    public void DoSomethingThatTriggersPriorEvents(int someValue)
    {
        Prior prior = someValue % 2 == 0 ? Prior.Moderate : Prior.Terminal;
        foreach (var script in _scripts)
        {
            if (script.Prior == prior)
            {
                script.Apply();
            }
        }
    }
}