昨天我经历了关于EventAggregator的一些article,有一些像这样编写的代码,
(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”。我的OOP理解是错误的吗?
答案 0 :(得分:5)
它在object
类上实现为Extension Method。
例如,这种扩展方法(来自链接文章):
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
在String
类上定义(使用this String
语法和静态类上的静态方法)。
在String
中定义的项目现在有一个WordCount
方法(只要它也在正确的命名空间中)。
答案 1 :(得分:2)
扩展方法实际上并不是您调用该方法的对象的一部分。扩展方法位于额外的查找范围内,编译器在查找对象本身范围内的方法后查找该范围。
因此,对于像obj.MyExtension()
这样的方法调用,编译器将在obj变量类型的成员中查找“MyExtension”。它不会找到任何匹配项,因为“MyExtension”未在对象的类型中定义。然后,编译器将查找名为“MyExtension”的扩展方法,这些扩展方法在当前范围内(由于using子句)可用,其具有this
参数,其类型与obj实例变量的类型匹配。如果找到了匹配项,那么编译器会生成代码以使用其他方法进行静态方法调用,并在this
参数中传递obj。
我认为扩展方法范围是“最后机会”查找 - 如果编译器在可用扩展中找不到“MyExtension”,则下一步是因编译错误而失败。
扩展方法的棘手之处在于,只有在将适当的using子句添加到当前源文件并且添加了对实现扩展的相应程序集的引用时才能访问它们进入范围。
Intellisense无法通过为您添加适当的using子句来帮助您解决这些名称。作为用户,您习惯于在特定类型的对象上调用特定方法,并且您在心理上将该方法关联为该类型的一部分。当您正在充实新的源文件时,通常会像往常一样编写对该方法的调用,并且因为您忘记将包含扩展方法定义的命名空间/程序集引用到您的“未找到”编译器错误,这是很常见的。源文件。
答案 2 :(得分:0)
this TEventsubject eventArgs
的这一部分确定这是Extension method。
能够写
只是语法糖TEventsubject eventArgs;
eventArgs.PublishEvent("topic");
而不是
TEventsubject eventArgs;
ExtensionServices.PublishEvent(eventArgs, "topic");
答案 3 :(得分:0)
PublishEvent
是一种扩展方法。
您可以通过方法的定义来判断,其中包含参数列表中的this
关键字。
http://msdn.microsoft.com/en-us/library/bb383977.aspx
扩展方法在语法上非常有用;但应明智地使用它们:
1)如果为非特定类型(例如对象)添加了太多扩展,它们会使Intellisense混乱。
2)它们应该用于扩充类/接口继承,而不是替换它。 IMO,如果方法在完全不相关的类型之间共享,那么它是扩展方法的一个很好的候选者。但是如果它是在相关类型之间共享的,那么它是基类中方法的更好选择。