c# – 将任何委托作为参数的构造方法

前端之家收集整理的这篇文章主要介绍了c# – 将任何委托作为参数的构造方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是简化的案例.我有一个类来存储它将在完成时调用的委托:
public class Animation
{
     public delegate void AnimationEnd();
     public event AnimationEnd OnEnd;
}

我有另一个实用工具类,我想订阅各种代表.在构造我想要自己注册代表,但除此之外它不关心类型.问题是,我不知道如何在类型系统中表达.这是我的伪C#

public class WaitForDelegate
{
    public delegateFired = false;

    // How to express the generic type here?
    public WaitForDelegate<F that's a delegate>(F trigger)
    {
        trigger += () => { delegateFired = true; };
    }
}

提前致谢!

感谢Alberto Monteiro,我只使用System.Action作为活动的类型.我现在的问题是,如何将事件传递给构造函数以便它可以自己注册?这可能是一个非常愚蠢的问题.

public class Example
{
    Animation animation; // assume initialized

    public void example()
    {
        // Here I can't pass the delegate,and get an error like
        // "The event can only appear on the left hand side of += or -="
        WaitForDelegate waiter = new WaitForDelegate(animation.OnEnd);
    }
}

解决方法

我担心你不能做你所要求的.

首先,你不能被代表约束.与合法C#最接近的代码是:

public class WaitForDelegate<F> where F : System.Delegate
{
    public bool delegateFired = false;

    public WaitForDelegate(F trigger)
    {
        trigger += () => { delegateFired = true; };
    }
}

但它不会编译.

但更大的问题是,无论如何你都无法像这样传递代表.

考虑这个简化的类:

public class WaitForDelegate
{
    public WaitForDelegate(Action trigger)
    {
        trigger += () => { Console.WriteLine("trigger"); };
    }
}

然后我尝试像这样使用它:

Action bar = () => Console.WriteLine("bar");

var wfd = new WaitForDelegate(bar);

bar();

唯一的输出是:

bar

单词触发器不会出现.这是因为代理是按值复制的,因此行trigger =()=> {Console.WriteLine(“trigger”); };只是将处理程序附加到触发器而不是bar.

您可以完成所有这些工作的方法是停止使用事件并使用Microsoft的Reactive Extensions(NuGet“Rx-Main”),它允许您将事件转换为基于LINQ的IObservable< T>可以传递的实例.

以下是我上面的示例代码如何工作:

public class WaitForDelegate
{
    public WaitForDelegate(IObservable<Unit> trigger)
    {
        trigger.Subscribe(_ => { Console.WriteLine("trigger"); });
    }
}

你现在称之为:

Action bar = () => Console.WriteLine("bar");

var wfd = new WaitForDelegate(Observable.FromEvent(h => bar += h,h => bar -= h));

bar();

这现在产生输出

bar
trigger

请注意,Observable.FromEvent调用包含用于在有权访问的作用域中附加和分离处理程序的代码.它允许通过调用.Dispose()来解除最终订阅调用.

我让这个课很简单,但更完整的版本是这样的:

public class WaitForDelegate : IDisposable
{
    private IDisposable _subscription;

    public WaitForDelegate(IObservable<Unit> trigger)
    {
        _subscription = trigger.Subscribe(_ => { Console.WriteLine("trigger"); });
    }

    public void Dispose()
    {
        _subscription.Dispose();
    }
}

如果您不想充分利用Rx,另一种方法是:

public class WaitForDelegate : IDisposable
{
    private Action _detach;

    public WaitForDelegate(Action<Action> add,Action<Action> remove)
    {
        Action handler = () => Console.WriteLine("trigger");
        _detach = () => remove(handler);
        add(handler);
    }

    public void Dispose()
    {
        if (_detach != null)
        {
            _detach();
            _detach = null;
        }
    }
}

你这样称呼它:

Action bar = () => Console.WriteLine("bar");

var wfd = new WaitForDelegate(h => bar += h,h => bar -= h);

bar();

那仍然是正确的输出.

原文链接:https://www.f2er.com/csharp/244920.html

猜你在找的C#相关文章