如何在C#中实现Signals(来自Django)概念

时间:2010-01-17 09:15:24

标签: c# django

我正在尝试从Django(http://docs.djangoproject.com/en/dev/topics/signals/)或其在C#中的概念实现信号,以减少/消除耦合/方法依赖性。

到目前为止,我正在复制代码,直到我意识到方法不是C#中的对象,就像在Python中一样。然后我想到了指针,然后我意识到我不能指向方法。它的C#版本是代理。

然后我意识到代理人有一个独特的签名,所以我不能真正将委托方法(带有差异签名)混合到List中,或者我可以吗?

我做了一些谷歌搜索,发现了Reactive LINQ,到目前为止,linq看起来很棒,但我还是不知道何时使用它们。

所以我的问题是,你如何在C#中实现Signals概念?谢谢!

哦,我提到我是新的(1天)到C#?我确实有各种其他语言的背景,包括Java / C / Python。

干杯:)

1 个答案:

答案 0 :(得分:2)

您在这里谈论的内容通常作为C#中的事件处理,例如;

public class SomeType {
    public event EventHandler SomeEvent;
    protected virtual void OnSomeEvent() {
        EventHandler handler = SomeEvent;
        if(handler!=null) handler(this,EventArgs.Empty);
    }
    public void SomethingInteresting() {
        // blah
        OnSomeEvent(); // notify subscribers
        // blap
    }
    // ...
}

订阅者......

SomeType obj = new SomeType();
//...
obj.SomeEvent += /* some handler */
//...

处理程序可以是一种方法,但在您对签名等的讨论中,使用不匹配签名重用现有方法的常用方法是使用匿名方法:

obj.SomeEvent += delegate { this.Text = "Done!"; };

可以有一个代表列表:

List<SomeDelegateType> list = new List<SomeDelegateType>();
list.Add(...);

但这可能是多余的,因为委托实例是多播 - 因此您可以更直接地执行此操作:

Action action = null;
action += delegate { Console.WriteLine("Did A");};
action += delegate { Console.WriteLine("Did B");};
action(); // does both A & B

请注意,更复杂的委托使用可能涉及传入的参数值 - 例如:

int i = 24;
Func<int,int,int> func = (x,y) => (x * i) + y;
int result = func(2, 3); // 51

通过将匿名方法(或lambdas,如上所述)与捕获的变量结合起来,签名必须匹配的问题很少成为问题 - 您可以使用lambda进行包装以使签名匹配(添加额外的值或删除参数,根据需要)。

请注意,对于事件(特别是),常见的方法是保留签名:

void SomeDelegateType(object sender, SomeArgsType args);

其中SomeArgsType : EventArgs - 或者使用EventHandler<T>来为您执行此操作。