简体   繁体   English

C#内部委托和公共事件

[英]C# Internal delegate and public Event

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. 根据这篇文章: http//msdn.microsoft.com/en-us/library/5z57dxz2.aspx (例2),我们需要为自定义事件提供委托。

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. 感谢帮助。

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. 我认为,如果您为自定义活动提供公共Delegate类型,那么任何人都可以提升该活动。

Well, that is not true. 嗯,那不是真的。 Only the class that defines that custom event can raise it. 只有定义该自定义事件的类才能引发它。 If this is your issue, don't worry. 如果这是您的问题,请不要担心。

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

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). 要实际调用您的事件,您通常会实现一个名为OnEvent的方法(您可以使用ClickClosed代替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. 您不能使用比事件“不可见”的委托来声明事件。

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. 而不是公共事件,创建一个手动订阅所需委托的方法,并将它们存储在`private List _delegates'字段中。

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. 或者,您可以接受它们不是公开Invoke()的事件的“按设计”功能。

:) :)

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. 如您所见, _foo字段是私有的,因此客户端代码无法访问它。 Only the event's add and remove accessors are accessible. 只能访问事件的addremove访问者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM