2010-12-02 2 views
2

Вчера я прошел через некоторый article о EventAggregator, есть некоторые выстрелы коды, написанная, как это,объект - как верхний базовый класс получил метод. [Метод расширения]

(Message.Text as object).PublishEvent(PublishEventNames.MessageTextChanged); 

public static class ExtensionServices 
    { 
     //Supplying event broking mechanizm to each object in the application. 
     public static void PublishEvent<TEventsubject>(this TEventsubject eventArgs, string eventTopic) 
     { 
      ServicesFactory.EventService.GetEvent<GenericEvent<TEventsubject>>() 
       .Publish(new EventParameters<TEventsubject> { Topic = eventTopic, Value = eventArgs }); 
     } 
    } 

Мой вопрос, как объект получил метод «PublishEvent». Является ли мое понимание ООП неправильным?

+0

Это функция языка C#? Какие еще языки поддерживают это? – Mohanavel 2010-12-02 18:46:29

ответ

5

Он был реализован как Extension Method на классе object.

Например, этот метод расширения (из связанной статьи):

public static class MyExtensions 
{ 
    public static int WordCount(this String str) 
    { 
     return str.Split(new char[] { ' ', '.', '?' }, 
         StringSplitOptions.RemoveEmptyEntries).Length; 
    } 
} 

определяется на String класса (с помощью this String синтаксиса и статического метода статического класса).

В проекте, который определен в String, теперь существует метод WordCount (при условии, что он также находится в правильном пространстве имен).

+0

+1 для Wordcount. Прекрасный пример. – Mohanavel 2010-12-02 18:47:50

0

Эта часть this TEventsubject eventArgs определяет, что это номер Extension method.

Это только синтаксический сахар, чтобы иметь возможность написать

TEventsubject eventArgs; 
eventArgs.PublishEvent("topic"); 

Вместо

TEventsubject eventArgs; 
ExtensionServices.PublishEvent(eventArgs, "topic"); 
0

PublishEvent является метод расширения.

По определению метода, который включает в себя ключевое слово this в списке аргументов.

http://msdn.microsoft.com/en-us/library/bb383977.aspx

Методы расширения являются очень полезными синтаксически; но их следует использовать разумно:

1) Они могут загромождать Intellisense, если для неспецифических типов (например, объекта) добавлено слишком много расширений.

2) Они должны использоваться для расширения класса/интерфейса, а не для его замены. IMO. Если метод используется совместно с полностью несвязанными типами, то он является хорошим кандидатом для метода расширения. Но если он разделяется между связанными типами, то он является лучшим кандидатом для метода в базовом классе.

2

Методы расширения на самом деле не являются частью объекта, на который вы хотите вызвать метод. Методы расширения находятся в дополнительной области поиска, которую компилятор просматривает после поиска метода в области самого объекта.

Итак, для вызова метода, такого как obj.MyExtension(), компилятор будет искать «MyExtension» в членах типа переменной obj. Он не найдет совпадений, потому что «MyExtension» не определен в типе объекта. Затем компилятор ищет методы расширения с именем «MyExtension», которые доступны в текущей области (из-за использования предложений), которые имеют параметр this, тип которого соответствует типу переменной экземпляра obj. Если совпадение найдено, то компилятор генерирует код, чтобы заставить статический метод вызывать этот другой метод, передавая obj в параметре this.

Я считаю, что область методов расширения - это «последний шанс» поиска - если компилятор не может найти «MyExtension» в доступных расширениях, следующим шагом будет сбой при ошибке компиляции.

Сложная вещь с методами расширения - они доступны только в том случае, если вы добавили соответствующее предложение использования в текущий исходный файл. и добавили ссылку на соответствующую сборку, которая реализует расширения для приведения их в область видимости.

Intellisense не поможет вам разрешить эти имена, добавив для вас соответствующее предложение use. Как пользователь вы привыкаете вызывать конкретный метод для определенного типа объекта, и вы мысленно ассоциируете этот метод как часть этого типа. Когда вы создаете новый исходный файл, очень часто приходится записывать вызовы этого метода, как обычно, и получать «не найденные» ошибки компилятора, потому что вы забыли ссылаться на пространство имен/сборку, содержащую определение (-ы) расширений исходный файл.

+1

+1 для упоминания проблем с разрешением Intellisense/easy namespace. Я нахожу это поведение раздражающим (а также противоположную проблему, о которой я упоминаю в своем ответе, т. Е. Много методов расширения, определенных для неспецифического типа, такого как System.Object). – 2010-12-02 18:43:05

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