object - How top most base class got Method. [Extension Method]
Yesterday i gone through开发者_StackOverflow社区 some article about EventAggregator, there some shot of code written like this,
(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 });
}
}
My question is, how the object got the method "PublishEvent". Is my OOP understanding is wrong?
It was implemented as an Extension Method on the object
class.
For example, this extension method (from the linked article):
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
Is defined on the String
class (by using the this String
syntax and a static method on a static class) .
In the project that this is defined in String
now has a WordCount
method (so long as it is also in the correct namespace).
Extension methods are not actually part of the object that you appear to call the method on. Extension methods are in an additional lookup scope that the compiler looks in after looking for the method in the scope of the object itself.
So, for a method call like obj.MyExtension()
, the compiler will look for "MyExtension" in the members of the type of the obj variable. It won't find any matches, because "MyExtension" isn't defined in the object's type. The compiler then looks for extension methods named "MyExtension" that are available in the current scope (because of using clauses) that have a this
parameter whose type matches the type of the obj instance variable. If a match is found, then the compiler generates code to make a static method call that other method, passing obj in the this
parameter.
I believe the extension methods scope is a "last chance" lookup - if the compiler can't find "MyExtension" in the available extensions, the next step is to fail with a compile error.
The tricky thing with extension methods is they're only accessible when you have added the appropriate using clause to the current source file and added a reference to the appropriate assembly that implements the extensions to bring them into scope.
Intellisense doesn't help you resolve these names by adding the appropriate using clause for you. As a user, you get used to calling a particular method on a particular type of object, and you mentally associate that method as being part of that type. When you're fleshing out a new source file it's very common to write calls to that method as you normally would and get "not found" compiler errors because you forgot to reference the namespace / assembly containing the extension method definition(s) to your source file.
The this part of this TEventsubject eventArgs
determines that this is an Extension method.
It is only syntactic sugar to be able to write
TEventsubject eventArgs;
eventArgs.PublishEvent("topic");
Instead of
TEventsubject eventArgs;
ExtensionServices.PublishEvent(eventArgs, "topic");
PublishEvent
is an extension method.
You can tell by the definition of the method, which includes the this
keyword in the arguments list.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Extension methods are very useful syntactically; but they should be used judiciously:
1) They can clutter Intellisense if too many extensions are added for non-specific types (such as an object).
2) They should be used to augment class/interface inheritance, not replace it. IMO, If a method is shared across completely unrelated types, then it is a good candidate for an extension method. But if it is shared across related types, then it is a better candidate for a method in a base class.
精彩评论