Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否向类方法添加事件?_C#_Events_Delegates_Methods - Fatal编程技术网

C# 是否向类方法添加事件?

C# 是否向类方法添加事件?,c#,events,delegates,methods,C#,Events,Delegates,Methods,好吧,我试过了,但就是不明白 我有两个班和一班 我有一个名为logger.Writestring的方法和一个名为class1.Execute的方法 public static ExecuteAndLog(this class1 obj) { logger.Write(obj.ToString()); obj.Execute(); } 现在在我的应用程序中,我希望在调用class1.Execute时运行logger.Writeclass1.ToString 我想你需要添加代表和事

好吧,我试过了,但就是不明白

我有两个班和一班

我有一个名为logger.Writestring的方法和一个名为class1.Execute的方法

public static ExecuteAndLog(this class1 obj)
{
    logger.Write(obj.ToString());
    obj.Execute();
}
现在在我的应用程序中,我希望在调用class1.Execute时运行logger.Writeclass1.ToString

我想你需要添加代表和事件,但我就是想不起来,已经抓了几个小时了


一件事是,logger和类位于不同的名称空间中,如果可能的话,我不想为它们中的任何一个更新类代码。

您能为logger传递一个对象参数,然后只调用该名称空间上的ToString吗?将调用适当的ToString方法。如果您不想更改logger或class1中的任何内容,那么可以编写一个扩展方法并调用它,而不是调用class1.Execute。此方法将调用logger,然后调用class1.Execute

public static ExecuteAndLog(this class1 obj)
{
    logger.Write(obj.ToString());
    obj.Execute();
}

然后您只需调用obj.ExecuteAndLog

如果您不想更改调用class1.Execute的所有地方,那么在不更改任何一个类中的代码的情况下,您当然无法做到这一点——至少在没有一些深层代码编织/插装魔法的情况下是这样。但是,您可以相当轻松地在Class1中添加事件:

委托{}位只是为了确保始终至少注册了一个no-op事件处理程序——这意味着您不需要检查空值

然后你可以写下:

Class1 class1 = new Class1();
Logger logger = new Logger();
class1.ExecuteCalled += (sender, args) => logger.Write(sender.ToString());
这是假设您使用的是C3,所以您可以使用lambda表达式-如果不是这样,请告诉我

如果Class1实现了一个接口(如IFoo),您可能希望编写一个接口的实现,该接口封装了另一个实现,并且在每次调用之前只记录日志:

public sealed class LoggingFoo : IFoo
{
    private readonly IFoo original;
    private readonly IFoo logger;

    public LoggingFoo(IFoo original, Logger logger)
    {
        // TODO: Check arguments for nullity
        this.original = original;
        this.logger = logger;
    }

    // Implement IFoo
    public void Execute()
    {
        logger.Write("Calling Execute on {0}", original);
        original.Execute();
    }
}
然后,只要在当前只使用该实现的地方使用该包装器就可以了。

您需要为Class1声明一个EventHandler

在执行方法中:

public void Execute()
{
   //...
   if (OnExecute != null)
       OnExecute(this, null);
}
然后当你在其他地方使用class1时,那就是你放置事件的地方

private Class1 class1 = new Class1();
class1.OnExecute += SomeMethodName;

public void SomeMethodName(sender obj, EventArgs e)
{
    logger.Write(class1.ToString());
}

如果您需要更多信息,我们可以为您定制EventHandler,但对于无参数事件,这应该是可行的。

这不是扩展方法设计的目的吗?这太完美了。现在我只需要了解它是如何工作的。我得到了第一个部分,但我假设=>后面的部分是替换class1事件处理程序中委托{}的部分。@Coding Monkey:=>表示lambda表达式。在这种情况下,这只是创建委托的一种简单方法。它不会替换原来的no-op处理程序;它添加了一个新的处理程序。当我再次在电脑上时,将使用指向我的事件文章的链接进行编辑。@jasonh:您可以编写一个扩展方法,以便每次都可以调用class1.Executelogger,当然-但我怀疑日志记录器的正常理想行为是隐式地保留class1。扩展方法不允许您添加新状态。@Jon Skeet:我明白您的意思。我的方法将两者明确地联系在一起,我可以看出这是不可取的。我想这一切都取决于程序的精确设计。jasonh的建议有什么问题?jasonh的建议是创建一个调用其他方法的方法。我一直在寻找事件方法的实现,因为我仍在试图了解它们是如何工作的。Jon的描述很有效,我现在知道了如何实现它们,我现在只需要知道它们是如何工作的。当一个扩展方法简洁地完成这项工作时,似乎仍然需要做很多额外的工作。如果你想用它来学习事件方法是如何工作的,我理解,但我不认为我会在生产代码中使用它,因为5行扩展方法也可以。嗯,实际上这很有效,但我必须更改调用。使用本应在我的类中开始的事件处理程序。那么,我有点困惑。你是说你不想修改你的应用程序、class1或logger?那么你是如何进入事件系统的呢?我的意思是,如果可能的话,我不想更新类,但我真正想说的是,我不想让类相互依赖。明白了。谢谢你的澄清!
private Class1 class1 = new Class1();
class1.OnExecute += SomeMethodName;

public void SomeMethodName(sender obj, EventArgs e)
{
    logger.Write(class1.ToString());
}