объект - Как верхний самый базовый класс получил метод. [Метод расширения] - PullRequest
2 голосов
/ 02 декабря 2010

Вчера я просмотрел некоторую статью о 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». Мое понимание ООП неверно?

Ответы [ 4 ]

5 голосов
/ 02 декабря 2010

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

2 голосов
/ 02 декабря 2010

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

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

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

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

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

0 голосов
/ 02 декабря 2010

PublishEvent - это метод расширения.

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

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

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

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

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

0 голосов
/ 02 декабря 2010

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

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

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

Вместо

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