Добавить событие в метод класса? - PullRequest
0 голосов
/ 11 июня 2009

Хорошо, я пытался, но я просто не понимаю.

У меня есть два класса logger и class1.

У меня есть метод с именем logger.Write(string) и метод с именем class1.Execute().

Теперь в моем приложении я хочу запустить logger.Write(class1.ToString()) при вызове class1.Execute().

Полагаю, вам нужно добавить делегатов и события, но я просто не могу разобраться с этим, поцарапал его пару часов.

Во-первых, регистратор и класс находятся в разных пространствах имен, и я не хочу обновлять код класса для любого из них, если это возможно.

Ответы [ 3 ]

6 голосов
/ 11 июня 2009

Что ж, вы определенно не можете сделать это без изменения кода в любом классе (при условии, что вы также не хотите менять везде, где вызывается class1.Execute) - по крайней мере, без некоторой глубокой магической обработки кода / инструментовки. Однако вы можете довольно легко добавить событие в Class1:

public class Class1
{
    // TODO: Think of a better name :)
    public event EventHandler ExecuteCalled = delegate {};

    public void Execute()
    {
        ExecuteCalled(this, EventArgs.Empty);
        // Do your normal stuff
    }
}

Бит delegate{} предназначен только для того, чтобы убедиться, что всегда есть хотя бы зарегистрированный обработчик события no-op - это означает, что вам не нужно проверять на ничтожность.

Затем вы подключите его, написав:

Class1 class1 = new Class1();
Logger logger = new Logger();
class1.ExecuteCalled += (sender, args) => logger.Write(sender.ToString());

(Предполагается, что вы используете C # 3, поэтому вам доступны лямбда-выражения - дайте мне знать, если это не так.)

Если 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();
    }
}

Тогда просто используйте эту обертку вокруг «реальной» реализации везде, где вы в данный момент просто используете реализацию.

2 голосов
/ 11 июня 2009

Можете ли вы передать объектный параметр для регистратора, а затем просто вызвать ToString для этого? Будет вызван правильный метод ToString. Если вы не хотите ничего менять в logger или class1, вы можете написать метод расширения и вызвать его вместо вызова class1.Execute. Этот метод будет вызывать logger, а затем вызывать class1.Execute.

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

И тогда вы просто вызовете obj.ExecuteAndLog ();

0 голосов
/ 11 июня 2009

Вам нужно будет объявить EventHandler для Class1

public event EventHandler OnExecute;

и в вашем методе execute:

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());
}

Мы можем сделать пользовательский EventHandlers, если вам нужна дополнительная информация, но для событий без параметров это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...