Home > Enterprise >  How do I create a public action, but keep the invoke private?
How do I create a public action, but keep the invoke private?

Time:12-25

Let say I have an action like this:

public Action OnSomeAction;

I would like to be able to subscribe to this action from outside of the class, but not be able to invoke it:

OnSomeAction.Invoke();

Is there a way to do this without making the action private and creating methods for subscribing and unsubscribing like this:

private Action _someAction;

public void Subscribe(Action listener)
{
    _someAction  = listener;
}

public void Unsubscribe(Action listener)
{
    _someAction -= listener;
}

private void Invoke()
{
    _someAction.Invoke();
}

CodePudding user response:

Are you looking for event?

public class MyClass {
  // Let firing event be private 
  private void onMyAction() {
    Action action = MyAction;

    if (action != null)
      action();
  }

  public void FireDemo() {
    onMyAction();
  }

  //TODO: I've put Action, but, probably, EventHandler will be a better choice
  // while event itself (subscribe / unsubscribe) being public
  public event Action MyAction;
}

Demo:


MyClass myClass = new MyClass();

var first = () => {Console.WriteLine("I'm the first")};
var second = () => {Console.WriteLine("I'm the second")};
var none = () => {Console.WriteLine("I should not fire")};

myClass.MyAction  = first;
myClass.MyAction  = second;
myClass.MyAction  = none;

// Unsubsribe
myClass.MyAction -= none;

// Direct attempt will NOT compile:
// myClass.MyAction();

myClass.FireDemo();

CodePudding user response:

Although this looks a lot like events. You can achieve it using Action too. Consider following code which is almost same as you suggested:

private List<Action> _someActionList = new List<Action>();

public void Subscribe(Action listener)
{
    _someActionList.Add(listener);
}

public void Unsubscribe(Action listener)
{
    _someActionList.Remove(listener);
}

private void Invoke()
{
    foreach(action in _someActionList)
    {
        action();
    }
}

I hope this is exactly what you want to do. If not then please elaborate further.

  • Related