4

I'm currently developing a tiny technical Framework that is independant of any applications. Business code just refers to this Framework.

According this article : http://msdn.microsoft.com/en-us/library/5z57dxz2.aspx (exemple 2), we need to provide a delegate for the custom event.

Problem is, anyone can Invoke my handler (and then raise the event), even in my Business Code and that isn't logical for me, so what is the best way to raise a custom Event with a delegate that is only "internal" and not "public" ?

Thanks for help.

Arnaud F.
  • 8,252
  • 11
  • 53
  • 102

5 Answers5

8

I am not sure if I get it right or not. I think that you feel like if you provide a public Delegate type for your custom event, anyone will be able to Raise that event.

Well, that is not true. Only the class that defines that custom event can raise it. If this is your issue, don't worry.

decyclone
  • 30,394
  • 6
  • 63
  • 80
5

Not true. It's not allowed to invoke an event outside the class which the event belongs to. Others can only use += and -= operators to your event. Only in the class, you can invoke the event. That is a difference between an event and a normal delegate. That is:

public Data
{
   public event EventHandler OnSave
   public EventHandler OnLoad;

   private void Load()
   {
       if (OnLoad!=null) OnLoad();  
       //other operations
   }
   private void Save()
   {
       if (OnSave!=null) OnSave();  
       //other operations
   }
}

And outside the class:

Data data = new Data();
data.OnLoad += (s,e) => {}; 
data.OnSave += (s,e) => {};
data.OnLoad = (s,e)=>{}; 
//data.OnSave = (s,e)=>{};  //invalid
data.OnLoad();
//data.OnSave();  //invalid
Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
3

The delegate is just a type declaration describing the "signature" of your event. This has to be public. To actually invoke your event you often implement a method named OnEvent (where you substitute Event with Click or Closed or whatever describes your event). This method should be private (or protected) in your class.

You cannot declare an event using a delegate that is less "visible" than the event.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • I'm looking at code that has "internal event SaveDelegate Save = null;" Does this mean that no event will happen, can't see the point of it. – AriesConnolly Aug 20 '20 at 14:23
  • @AriesConnolly: `internal` is like `public` except it's limited to the same assembly. Even if the event was `private` it could still happen but then only the class with the event would be able to handle it. And since this is also the class that raises events it seems a bit pointless. Modern C# development tools can show you both where in the code the event is raised and where it's handled. – Martin Liversage Aug 20 '20 at 15:56
1

One way of doing it:

Instead of public event, create a method that will manually subscribe your desired delegates, and store them in `private List _delegates' field.

Then, from the 'inside', call each of them when you desire.

public class Framework 
{
    public delegate void Method();
    public void AttachEvent(Method M)
    {
         _methods.Add(M);
    }
    private List<Method> _methods;
    private FireMethods() 
    {
         _methods.Foreach(x=>x.Invoke());
    }
}

Or, you can embrace 'by design' feature of the events that they aren't publicly Invoke()-able.

:)

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
1

Problem is, anyone can Invoke my handler (and then raise the event), even in my Business Code

That isn't true. You declare an event as follows:

public event FooEventHandler Foo;

The only thing that external code can do with the event is subscribe to it (+=), or unsubscribe from it (-=). It can't access the actual delegate, which is generated by the compiler as a private field. In other words, this code would be invalid :

SomeClass x = new SomeClass();
x.Foo(x, new FooEventArgs()); // compilation error here

Don't forget that an event is actually a pair of methods (add and remove). The compiler rewrites the event declaration to something along those lines:

private FooEventHandler _foo;

public event FooEventHandler Foo
{
    add { _foo += value; }
    remove { _foo -= value; }
}

(the generated code is actually a bit more complex, with some locking to ensure thread safety)

As you can see, the _foo field is private, so client code can't access it. Only the event's add and remove accessors are accessible.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758