将事件作为参数传递

时间:2015-09-07 14:01:47

标签: c# events delegates

我使用库 [1] 定义了一些我想要使用的东西:

public delegate void FooHandler(int i);
public delegate void BarHandler(string s);

public class Foo
{
    public event FooHandler Fooh;
}

public class Bar
{
    public event BarHandler Barh;
}

我想有一个短暂的记忆,我可以"附加"对这些事件:

public class ShortTermMemory<T>
{

    public ShortTermMemory(??? arg)
    {
        arg += t => Remeber = t;
    }

    public T Remember { get; private set; }
}

并将它们附加到像

这样的地方
var foo = new Foo();
var bar = new Bar();
var intmemory = new ShortTermMemory<int>(foo.Fooh);
var stringmemory = new ShortTermMemory<string>(bar.Barh);

这是不可能的,因为:

  • ???是(有点可以理解)不是有效的类型声明,
  • &#34;该事件只能在+ =或 - =&#34;
  • 的左侧使用

我能做些什么来解决这个问题,或者在C#中根本不可能做到这一点?我希望编译时保证ShortTermMemory只是&#34;馈送&#34;通过一个事件源,在编译时已知有一个类型为T的参数。

[1]:仅用于演示目的的示例实现

2 个答案:

答案 0 :(得分:1)

使用编译时保证您期望它在C#中不可能。那里有一些问题:

  1. event由私有委托字段支持,该字段具有组合的调用列表。这被视为实现细节,因此是私有访问。
  2. 我们需要引用事件的委托字段,以便将addremove+= / -=)运算符应用于Delegate.Combine / { {1}}。
  3. 由于C#将委托作为自己的类型处理,我们应该对RemoveFooHandler都有一个通用的定义。
  4. 您错过了事件的取消订阅,可能放在BarHandler的析构函数中。目前,事件对象可能不再存在,请参阅How to save a ref variable for later use?

答案 1 :(得分:-1)

工作解决方案:

public delegate void Handler<T> ( T i );

public class Foo
{
    public event Handler<int> Fooh;

    public void Set(int i) {
        if (Fooh != null) {
            Fooh(i);
        }
    }
}

public class ShortTermMemory<T>
{
    object obj = null;
    string eventName;
    Handler<T> handler;

    public ShortTermMemory (object obj, string eventName) {
        this.obj = obj;
        this.eventName = eventName;
        this.handler = new Handler<T>(Set);

        Type type = obj.GetType();
        EventInfo info = type.GetEvent(eventName);

        info.AddEventHandler(obj, handler);
    }

    ~ShortTermMemory() {
        if (obj != null) {
            Type type = obj.GetType();
            EventInfo info = type.GetEvent(eventName);

            info.RemoveEventHandler(obj, handler);
        }
    }

    public T Remember { get; set; }

    public void Set(T t) {
        Remember = t;
    }
}

var foo = new Foo();
var intmemory1 = new ShortTermMemory<int>(foo, "Fooh");
var intmemory2 = new ShortTermMemory<int>(foo, "Fooh");

foo.Set(10);