События / интерфейсы C # - получение обратных вызовов без подписки на каждый класс, использующий интерфейс - PullRequest
0 голосов
/ 07 ноября 2018

Я изучаю интерфейсы и события, и пока все хорошо, но я застрял на одной проблеме.

В мои дни использования интерфейсов C # я привык объявлять, какой интерфейс использовать, затем реализовывать связанные методы, и они получают автоматические обратные вызовы всякий раз, когда происходит событие.

Например, Unity's 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? Просто реализуя интерфейс и получая автоматические обратные вызовы при возникновении события, как в IPointerClickHandler в Unity.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Как бы я создал интерфейс, где мне не нужно вручную подписаться и отписаться на событие? Есть ли способ реализовать интерфейс и не нужно использовать Publisher.OnClicked + = Teleport; Просто реализуя интерфейс и получая автоматические обратные вызовы при возникновении события, как в IPointerClickHandler в Unity.

Да.

Ваш пример интерфейса:

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 для выполнения события. Это сложнее, но стоит знать.

0 голосов
/ 07 ноября 2018

Вы не можете автоматически подписаться на событие, но вы можете переместить свой код подписки в абстрактный класс и наследовать его в каждом классе, где вы хотите реализовать 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");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...