首先,简单的问题。
当MEF(System.ComponentModel.Composition)创建部件的实例时,是否可以接收event
?
当发生这种情况时,我想反思创建的对象并连接各种属性。在Spring.Net中,可以使用IObjectPostProcessor
接口。
背景是我尝试在MEF中实现Publisher / Subscriber模式。基本上订阅者类这样做:
class MyContoller
{
[Command("Print")]
public void Print() { ... }
[Command("PrintPreview")]
public void PrintPreview() { ... }
}
我想检测MyController何时被实例化并连接具有CommandAttribute
的任何方法。
发布商(例如菜单项)会Command.Get("Print").Fire()
发布上述事件。
第二个问题
也许在MEF中有一种我缺少的替代模式!!!
我看过一些关于MEF, Prism and the Event Aggregate的帖子,但看起来相当复杂。
FYI
仅供参考,这是Spring.Net实现的原始内容:
class CommandAttributeProcessor : IObjectPostProcessor
{
static ILog log = LogManager.GetLogger(typeof(CommandAttributeProcessor));
public object PostProcessAfterInitialization(object instance, string objectName)
{
foreach (MethodInfo methodInfo in instance.GetType().GetMethods())
{
foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true))
{
if (log.IsDebugEnabled)
log.Debug(String.Format("Binding method '{0}.{1}' to command '{2}'.", instance.GetType().Name, methodInfo.Name, attr.CommandName));
Command command = Command.Get(attr.CommandName);
command.Execute += (EventHandler) Delegate.CreateDelegate(typeof(EventHandler), instance, methodInfo);
}
}
return instance;
}
public object PostProcessBeforeInitialization(object instance, string name)
{
return instance;
}
}
答案 0 :(得分:3)
这可能没有帮助,但部件本身可以在完全组合时收到通知:
Automatically call method after part has been composed in MEF
此外,您可能已经知道这一点(并且它可能与您尝试做的事情无关),但您可以装饰您的导出和导入,例如具体实现已命名。所以,你可以有一个像这样的导出类:
[Export("Print", typeof(IPlugin))]
[PartCreationPolicy(CreationPolicy.Shared)]
class Print : IPlugin
{
.
.
.
public Fire()
{
//Do something;
}
}
class PrintMenuItem
{
IPlugin _plugin;
[ImportingConstructor]
PrintMenuItem([Import("Print", typeof(IPlugin)] plugin)
{
_plugin = plugin;
}
void Execute()
{
_plugin.Fire();
}
}
答案 1 :(得分:1)
您可以使用MEF Contrib的InterceptingCatalog(MEF Contrib on codeplex或者您可以通过nuGet安装它)并实现IExportedValueInterceptor接口来连接具有CommandAttribute的方法:
//using System.ComponentModel.Composition;
//using System.ComponentModel.Composition.Hosting;
//using MefContrib.Hosting.Interception;
//using MefContrib.Hosting.Interception.Configuration;
public class CommandAttributeProcessor : IExportedValueInterceptor
{
public object Intercept(object value)
{
foreach (MethodInfo methodInfo in value.GetType().GetMethods())
{
foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true))
{
// do something with command attribute
}
}
return value;
}
}
在创建MEF目录时,需要在拦截器(CommandAttributeProcessor)中添加拦截配置,并将目录包装在InterceptingCatalog中,如下所示:
InterceptionConfiguration interceptionConfiguration = new InterceptionConfiguration();
interceptionConfiguration.AddInterceptor(new CommandAttributeProcessor());
InterceptingCatalog interceptingCatalog = new InterceptingCatalog(assemblyCatalog, interceptionConfiguration);
CompositionContainer container = new CompositionContainer(interceptingCatalog);