为事件分配指针以供稍后使用

本文关键字:事件 分配 指针 | 更新日期: 2023-09-27 18:04:31

这有点难以表达,所以我将主要依靠代码。

顺便说一句,如果你能更好地表达这个问题不要犹豫,给你的2c!

class CustomEventArgs : EventArgs
{
    public delegate void CustomEventHandler( Object sender, CustomEventArgs args );
    public int data;
    public CustomEventArgs (int _data)
    {
        data = _data;
    }
}

这是我们将在本例中使用的事件。

class EventGenerator
{
    public event CustomEventArgs.CustomEventHandler WeOccasion;
    public EventGenerator ()
    {
        Task.Factory.StartNew( () =>
            {
                var index = 1;
                // just loop and generate events every now and then
                while (true)
                {   
                    Thread.Sleep( 1000 );
                    WeOccasion( this, new CustomEventArgs (++index));
                }
            });
    }
}

这个类只是循环触发CustomEventHandler事件。

class EventActivity
{
    // EventActivity has an event of the same type as EventGenerator's 
    public event CustomEventArgs.CustomEventHandler WeOccasion;
    // this is the part I cant seem to get right
    public event CustomEventArgs.CustomEventHandler Source ( get; set; }
    public bool Active {
        set
        {
            if (value)
            {
                Source += DoWork;
            }
            else
            {
                Source -= DoWork;
            }
        }
    }
    private void DoWork( Object sender, CustomEventArgs frame);
}
这是我真正需要帮助的地方。我想要一个指向另一个类型为CustomEventHandler的类中的事件的指针,我可以稍后在激活活动时为其分配事件处理程序。

这是一个用类封装的用法示例;

class EventAssigner
{
    EventGenerator Generator;
    EventActivity DoSomeThing1;
    EventActivity DoSomeThing2;
    public EventAssigner ()
    {
        // init
        Generator = new EventGenerator();
        DoSomeThing1 = new EventActivity();
        DoSomeThing2 = new EventActivity();
        // assign sources
        DoSomeThing1.Source = Generator.WeOccasion;
        DoSomeThing2.Source = DoSomeThing1.WeOccasion;
        // activate the first activity
        DoSomeThing1.Active = true;
    }
    public void Activate2()
    {
        // activate the second activity
        DoSomeThing2.Active = true;
    }
    public void Deactivate2()
    {
        // deactivate the second activity
        DoSomeThing2.Active = false;
    }
}

显然这段代码不起作用,我想这就是我要问的。你能让这种设计模式发挥作用吗?

为事件分配指针以供稍后使用

对于。net事件,您要求做的事情实际上是不可能的,并且可能不像您想象的那样令人满意。一点背景知识应该有助于解释为什么:

属性具有get和set操作的基本模式。可以通过访问属性(对于get)和对属性赋值(对于set)来调用:

var x = instance.Prop1; // access
instance.Prop1 = x; // assignment

当您从类外部访问事件(即instance.Event)时,您将获得"公共"面,这与属性一样,有两个操作:添加处理程序和删除处理程序。这些是使用+=-=操作符调用的。

instance.Event += this.Handler; // add
instance.Event -= this.Handler; // remove
重要的是要注意它没有"get"操作- 没有办法在类之外获取对事件的引用;您只能修改已注册的处理程序。

当你从一个类中访问一个事件时,你会得到一个"私有"面,它本质上是一个特殊的委托集合(函数指针)到注册的事件处理程序。当你调用委托时,你实际上是在要求框架遍历注册的事件处理程序并调用它们。

if(this.Event != null)
{
    this.Event.Invoke(e, args); // raise event
}

这种公共面孔和私人面孔的分离是什么让你有一个简单的event关键字,神奇地给你一个事件。这也是阻止您传递对事件的引用的原因。

要将事件传递给注册方法,必须传递事件所附加的对象。如果你有多个实现相同事件的类,并且你想以相同的方式注册它们,你应该让它们实现一个带有事件的接口(是的,事件可以在接口上),并编写你的方法来接受接口作为参数。

如果我没看错的话,你想要

DoSomeThing1.Source = Generator.WeOccasion;

保存指向WeOccasion事件的指针,以便稍后添加DoWork调用,对吗?

我认为这在"正常"代码中是不可能的,因为事件不是一个值,而更像是一个属性。考虑下面的类似代码:

myProp = aPerson.Name; // attempt to save the name property for later
myProp = "Fred"; // intent is to set aPerson.Name = "Fred"

如果你想这样做,我建议使用反射来找到事件,并使用EventInfo添加到它。AddEventHandler方法(http://msdn.microsoft.com/en-us/library/system.reflection.eventinfo.addeventhandler.aspx)