将可订阅的Action作为参数传递

时间:2018-06-01 02:36:03

标签: c# events action

我有一个事件,我需要在构造函数中订阅一个方法,所以我想传递事件(Action OnNewGps),如下所示:

public AccelCalculator(SensorManager sensorManager, Action<double, double> OnNewData, Action<GPSReading> OnNewGps)
{
    this.sensorManager = sensorManager;
    sensorManager.OnNewAccelReading += CalibrateAccel;
    OnNewGps += ProcessGPS;
    OnNewDataCalculation += OnNewData;
}

构造函数方法本身并没有给我任何错误,但是我无法通过引用locationManager实例从另一个类调用它:

accelCalculator = new AccelCalculator(sensorManager, RecordAccel, locationManager.OnPositionUpdated );

由于:

  

事件&#39; LocationManager.OnPositionUpdated&#39;只能出现在+ =或 - =

的左侧

定义了LocationManager.OnPositionUpdated:

public event Action<GPSReading> OnPositionUpdated;

1 个答案:

答案 0 :(得分:0)

我们应该记住两点。

第一

您可以将该事件作为参数传递给构造函数但仅当您创建的对象停留在持有该事件的类的范围内时。

请参阅下面的错误消息。

  

活动&#39; PublisherClass.Event&#39;只能出现在+ =或 - = 的左侧(除非在类型&#39; PublisherClass&#39;中使用)

当您尝试引发/传递停留在声明它的类之外的事件时,会发生此错误。

所以留在课堂内,我们可以提高并传递事件作为参数!

现在我们知道,如果我们创建订阅者实例(调用订阅者的构造函数),我们肯定可以将Event传递给构造函数。 我在这个答案的后半部分已经证明了这一点。

但这不是使用事件的好习惯。

通常(和首选方式),发布者类永远不应该拥有Subscriber类的对象。相反,订阅者类应该拥有发布者类的对象。

原因很简单,如果发布者有订阅者的对象,它可以直接调用订阅者的方法(没有提出事件来执行订阅者的功能)。

第二

事实上,在您的代码中,您不会在发布商中创建订阅者;对你有益。但同样的事实将限制您将发布者的事件传递给构造函数的事件。

这也是必需的         如果活动可以在课程外完全访问,那么也可以         任何外部调用都可以操纵它。         例如。如果一个活动是由少数订阅者订阅的,               和一些局外人调用,给它分配null。               所有它的订阅都将消失。               我们可以使用封装的概念                   避免在代码内部完成(不应公开暴露操纵代码)

您可以做的最好的事情是将发布者的对象传递给订阅者的构造函数,并将其传递给订阅者的构造函数;您可以使用适当的方法订阅您想要的活动。如下。

public delegate Object EventType();
public class PublisherClass
{
    private event EventType Event;

    public event EventType EventAccessor
    {
        add { Event += value; }
        remove { Event -= value; }
    }

    public void RaiseAnEvent()
    {
        if (Event != null) { Event(); }
    }
}

订阅者类

public class SubscriberClass
{
    public SubscriberClass(PublisherClass p)
    {
        p.EventAccessor += d_Event;
    }

    object d_Event()
    {
        return null;
    }
}

以及您正在创建订阅者对象的另一个类,以及发布者的引用。

    static void Main(string[] args)
    {
        PublisherClass p = new PublisherClass();
        SubscriberClass s = new SubscriberClass(p);
        p.RaiseAnEvent();   
    }

以下是您如何将事件作为参数传递(但不是上面提到的良好做法)

该事件必须采取和返回的任何参数和返回类型,为它创建一个委托。

假设您需要一个返回object的方法(在您的情况下为Action<GPSReading>

public delegate Object EventType();

如果订阅者类正在

现在在发布商类中声明了EventType

的事件
public delegate Object EventType();
public class PublisherClass
{
    public event EventType Event;

    public PublisherClass()
    {
        SubscriberClass d2 = new SubscriberClass(ref Event);
        if (Event != null)
        {
            Event();
        }
    }
}

订阅者类

public class SubscriberClass
{
    public SubscriberClass(ref EventType eve)
    {
        eve += d_Event;
    }

    object d_Event()
    {
        return null;
    }
}