C#事件/接口-获得回调而无需订阅使用该接口的每个类

时间:2018-11-07 16:57:19

标签: c# unity3d events interface

到目前为止,我正在学习有关接口和事件的知识,但是我只停留在一个问题上。

在使用C#接口的日子里,我习惯于声明要使用的接口,然后实现相关的方法,并在发生事件时自动获得回调。

例如Unity的IPointerClickHandler

using UnityEngine; using UnityEngine.EventSystems;

public class Example : MonoBehaviour, IPointerClickHandler {
    //Detect if a click occurs
    public void OnPointerClick(PointerEventData pointerEventData)
    {
        //Output to console the clicked GameObject's name and the following message. You can replace this with your own actions for when clicking the GameObject.
        Debug.Log(name + " Game Object Clicked!");
    } }

现在,在查看有关如何使用事件和接口的示例时,我发现以下示例:

发布者类和接口

using UnityEngine;
using System.Collections;

public class Publisher : MonoBehaviour
{
    public delegate void ClickAction();
    public static event ClickAction OnClicked;


    void Start()
    {
          OnClicked();
    }

}


public interface IBallManager
{
    void Teleport();

}

订户类别:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Subscriber : MonoBehaviour, IBallManager
{

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    void OnEnable()
    {
        Publisher.OnClicked += Teleport;
    }

    void OnDisable()
    {
        Publisher.OnClicked -= Teleport;
    }

    public void Teleport()
    {
        Debug.Log("EventTriggered");
    }

}

我的问题如下:我如何构建无需手动订阅和取消订阅事件的界面?有没有一种方法可以实现一个界面,而不必使用Publisher.OnClicked + = Teleport; &Publisher.OnClicked-=传送;在每个使用IBallManager的类中?只需实现接口并在事件引发时获取自动回调,就像在Unity的IPointerClickHandler中一样。

谢谢!

2 个答案:

答案 0 :(得分:2)

您不能自动订阅事件,但是可以将预订代码移至抽象类,并在要实现IBallManager的每个类中继承它:

public abstract class BaseSubscriber: MonoBehaviour, IBallManager
{
    public virtual void OnEnable()
    {
        Publisher.OnClicked += OnPublisherClicked;
    }

    public virtual void OnDisable()
    {
        Publisher.OnClicked -= OnPublisherClicked;
    }

    protected abstract void OnPublisherClicked();
}

像下面那样在您的具体订阅者中继承它,基类将为您完成订阅工作:

public class Subscriber: BaseSubscriber
{
    public override void OnEnable()
    {
        // Do smth here
        base.OnEnable();
    }

    public override void OnDisable()
    {
        // Do smth here
        base.OnDisable();
    }

    protected override void OnPublisherClicked()
    {
        Debug.Log("EventTriggered");
    }
}

答案 1 :(得分:1)

  

我将如何构建无需手动操作的界面   订阅和取消订阅活动?有没有办法实现   界面,而不必使用Publisher.OnClicked + = Teleport;只需实现接口并在事件引发时获取自动回调,就像在Unity的IPointerClickHandler中一样。

是的

您的示例界面:

public interface IClicker
{
    void Click();
}

实现界面的类:

public class Clicker : MonoBehaviour, IClicker
{
    public void Click()
    {

    }
}

要调用该函数,请在GameObject中找到具有实现该接口的脚本的脚本,并以GetComponent获取该接口,如果不是null,则调用其函数。如果是null,则该类未实现该接口。

GameObject targetObj = GameObject.Find("Obj with Interface");
IClicker clicker = targetObj.GetComponent<IClicker>();

if (clicker != null)
    clicker.Click();

您还可以使您的界面源自IEventSystemHandler

public interface IClicker : IEventSystemHandler
{
    void Click();
}

然后使用ExecuteEvents.ValidateEventData验证实现接口的类,并使用ExecuteEvents.Execute执行事件。这比较困难,但值得一提。