簡體   English   中英

C#事件/接口-獲取回調而無需訂閱使用該接口的每個類

[英]C# Events / Interfaces - Getting Callbacks without subscribing in every class that's using the 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中。

提前致謝!

您不能自動訂閱事件,但是可以將訂閱代碼移至抽象類,並在要實現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");
    }
}

我將如何構建無需手動訂閱和取消訂閱事件的界面? 有沒有一種方法可以實現一個界面,而不必使用Publisher.OnClicked + = Teleport; 只需實現接口並在事件引發時獲取自動回調即可,例如在Unity的IPointerClickHandler中。

是。

您的示例界面:

public interface IClicker
{
    void Click();
}

實現界面的類:

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

    }
}

要調用該函數,請使用實現接口的腳本找到GetComponent腳本,使用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來執行該事件。 這比較困難,但是值得知道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM