2009-06-11 5 views
0

ОК, я пробовал, но я просто не понимаю.Добавить событие в метод класса?

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

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

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

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

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

+0

что не так с предложением Джейсона? – RCIX

+0

Предложение jasonh о создании метода, который вызывает другие методы. Я искал реализацию методов событий, поскольку я все еще пытаюсь понять, как они работают. Описание Jon работает, и теперь я понимаю, как их реализовать, мне просто нужно понять, как они работают. –

+0

Это по-прежнему кажется большим количеством дополнительной работы, когда метод расширения делает работу лаконично. Я понимаю, если вы хотите использовать его, чтобы узнать, как работают методы событий, но я не думаю, что я буду использовать это в производственном коде, когда метод расширения с 5 строками будет таким же. – jasonh

ответ

6

Ну, вы, конечно же, не можете это сделать, не меняя код в любом классе (предполагая, что вы также не хотите менять везде, что вызывает 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{} бит просто чтобы убедиться, что всегда есть по крайней мере, не оп зарегистрированный обработчик события - это не означает, что вам не нужно, чтобы проверить недействительность.

Вы бы затем подключить его в письменной форме:

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

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

+0

Разве это не метод расширения? – jasonh

+0

Это прекрасно. Теперь я просто должен понять, как это работает. Я получаю первую часть, но я предполагаю, что часть после => является частью, которая заменяет делегат {} в обработчике события в классе1. –

+0

@Coding Monkey: => означает выражение лямбда. В этом случае это просто простой способ создания делегата. Он не * заменяет * оригинальный обработчик no-op; он добавляет * новый * обработчик. Будет редактировать со ссылкой на статью о событиях, когда я снова нахожусь на ПК. –

2

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

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

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

+0

Хм, на самом деле это хорошо работает, но мне придется менять вызовы. Использование обработчика событий, который должен был быть в моем классе для начала. –

+0

Ну, я немного смутился. Вы говорите, что не хотите изменять свое приложение, class1 или logger? Как вы получаете систему событий тогда? – jasonh

+0

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

0

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

public event EventHandler OnExecute; 

и в вашем выполнения метода:

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, если вы хотите получить больше информации, но для баребонов событий без параметров это должно работать.

Смежные вопросы