QuantumSno
QuantumSno

Reputation: 1

Abstraction of delegates

Background; this is part of a button system for a dialog menu. Buttons can either take you to new conversation paths or out of the conversation. It uses Event Actions for when a button is pressed to trigger what happens next.

It uses these events by subscribing the 'next operation' to one event, then subscribing a lamda of unsubscribing that event to every other event.

In sudo code where button_one and button_two are events

button_one += SomethingFancy()

button_two += button_one -= SomethingFancy()

So the question is: is there a way to abstract a series of these into one function? This works fine but is messy and unclean, so is there a better option?

The Program:

or at least part of it. I took out some unnecessary code

Glossary:

toggleUI and its .Option are turning on buttons

dialog is a scriptable object that holds data for each conversation state. It has Lists of dialog with a character and the text they speak

buttonAction just checks to see if the dialog leads to more text or the end of the conversation

   public event Action ButtonOne;
   public event Action ButtonTwo;
   public event Action ButtonThree;

private void PostDialog(ScriptableDialog dialog) {
   if (dialog.OptionOne.Text != string.Empty) {
      toggleUI.OptionOne = true;
      toggleUI.SetButtonText(1, dialog.OptionOne.Text);
      // These chunky chunks
      ButtonOne += () => buttonAction(dialog.OptionOne);
            
      ButtonOne -= () => buttonAction(dialog.OptionOne);
      ButtonTwo += () => ButtonOne -= () => buttonAction(dialog.OptionOne);
      ButtonThree += () => ButtonOne -= () => buttonAction(dialog.OptionOne);
   }
   if (dialog.OptionTwo.Text != string.Empty){
      toggleUI.OptionTwo = true;
      toggleUI.SetButtonText(2, dialog.OptionTwo.Text);
      // These chunky chunks
      ButtonTwo += () => buttonAction(dialog.OptionTwo);

      ButtonTwo -= () => buttonAction(dialog.OptionTwo);
      ButtonOne += () => ButtonTwo -= () => buttonAction(dialog.OptionTwo);
      ButtonThree += () => ButtonTwo -= () => buttonAction(dialog.OptionTwo);
   }
   if (dialog.OptionThree.Text != string.Empty) {
      toggleUI.OptionThree = true;
      toggleUI.SetButtonText(3, dialog.OptionThree.Text);
      // These chunky chunks
      ButtonThree += () => buttonAction(dialog.OptionThree);

      ButtonThree -= () => buttonAction(dialog.OptionThree);
      ButtonTwo += () => ButtonThree -= () => buttonAction(dialog.OptionThree);
      ButtonOne += () => ButtonThree -= () => buttonAction(dialog.OptionThree);
   }
}

Little bit of a strange request, but it would be awesome if there was an answer.

I found this video by Sebastian Lague talking about delegates that I think has the answer, but I cant wrap my brain around it yet, so maybe that could help. https://youtu.be/G5R4C8BLEOc?t=156

I can show of the code somewhere is you want, just let me know.

Upvotes: 0

Views: 55

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70701

is there a way to abstract a series of these into one function?

It depends on what you mean. You can't pass an event to a method, so (without using reflection, which you should avoid) you can only write a method that is specific to a given event. But you certainly can do that:

void SubscribeButtonEvents(EventHandler handler)
{
    EventHandler handler2 = null;

    handler2 = (sender, e) =>
    {
        button_one -= handler;
        button_two -= handler2;
    }

    button_one += handler;
    button_two += handler2;
}

The key here is to save the delegate instance being subscribed. In the above, there are two handlers that get captured by the lambda created in the method, since (presumably) you really want to unsubscribe both handlers.

Then you call the method like this:

SubscribeButtonEvents(SomethingFancy);

Where SomethingFancy() is of course a method with the appropriate EventHandler signature.

If you do need to create a single method that can deal with any arbitrary pair of events, then you will need to use reflection. Not advisable, but it can be done.

Of course, there certainly are other possible approaches, many of them likely superior to this. The question is a bit open-ended and arguably should be improved so that it's not. But taking what appears to be the primary question that was asked, the above addresses that exactly.

Upvotes: 1

Related Questions