C# 了解MEF系统。懒惰<;T、 TMetaData>;
我一直在研究这个系统的内部工作原理 在这个RI中,MEF和一个自定义属性系统被结合使用来注册带有区域的视图,而不是在模块初始值设定项中将内容连接到RegionManager 更具体地说,有一个C# 了解MEF系统。懒惰<;T、 TMetaData>;,c#,mvvm,prism,mef,C#,Mvvm,Prism,Mef,我一直在研究这个系统的内部工作原理 在这个RI中,MEF和一个自定义属性系统被结合使用来注册带有区域的视图,而不是在模块初始值设定项中将内容连接到RegionManager 更具体地说,有一个ViewExportAttribute,它实现: MetaDataAttribute IViewRegion注册 元数据属性和“属性视图”IViewRegionRegistration可由System.Lazy在AutoPopulateExportedViewsBehavior中使用,以实现区域和视图的正确
ViewExportAttribute
,它实现:
MetaDataAttribute
IViewRegion注册
IViewRegionRegistration
可由System.Lazy
在AutoPopulateExportedViewsBehavior
中使用,以实现区域和视图的正确链接
一般来说,System.Lazy
和实际元数据之间的相互作用将在“使用强类型元数据”一节中详细阐述
说清楚一点,我理解懒惰的意图,而且它显然有效。但是,我完全不理解的是属性提供的元数据视图(只是一个接口)与使用MetaDataAttribute提供的实际数据填充TMetaData属性之间的链接发生在何处以及如何发生
为了让我的要求更加明确,请访问:
首先,定义了一个接口,该接口可以用作传递特定元数据的某种模板:
public interface IMessageSenderCapabilities
{
MessageTransport Transport { get; }
bool IsSecure { get; }
}
接下来,定义一个对应的MetaDataAttribute(其属性与前面的接口相同)
该属性可用于导出,其中为属性属性设置了实际值:
[MessageSender(Transport=MessageTransport.Smtp, IsSecure=true)]
public class SecureEmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
最后,我们可以进行一些导入:
public class HttpServerHealthMonitor
{
[ImportMany]
public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }
public void SendNotification()
{
foreach(var sender in Senders)
{
if (sender.Metadata.Transport == MessageTransport.Smtp &&
sender.Metadata.IsSecure)
{
var messageSender = sender.Value;
messageSender.Send("Server is fine");
break;
}
}
}
}
公共类HttpServerHealthMonitor
{
[进口数量]
公共延迟[]发送者{get;set;}
公共通知()
{
foreach(发送方中的var发送方)
{
if(sender.Metadata.Transport==MessageTransport.Smtp&&
sender.Metadata.IsSecure)
{
var messageSender=sender.Value;
messageSender.Send(“服务器正常”);
打破
}
}
}
}
在最后一步中:
sender.Metadata.Transport
是在这个非常懒惰的基础上计算的。因此,在这个过程中的某个地方,Lazy会知道元数据的实际值,而不仅仅是它所传递的接口我想了解这是如何发生的,是谁或什么原因造成的。即使这只是一个非常一般的流程。经过更多的反射器,我想我可以开始制定一个答案,尽管事实证明很多事情正在发生,所以这个答案可能会演变。我把它写下来是为了自己学习这个
MEFBootsrapper.Run()
MEFBootstrapper.Container.GetExports(…)
因为CompositionContainer:ExportProvider,
和ExportProvider定义了public Lazy GetExport()
private Lazy GetExportCore(string contractName)
内部静态延迟创建stronglytypedlazyoftm(导出)
AttributedModelServices.GetMetadataView(export.Metadata)
其中M是MetaDataView的类型。而导出本身属于类型System.ComponentModel.Composition.Primitives.export
,它有一个字段exportDefinition
,其中存在一个继承的attributeExportDefinition
AttributeExportDefension.MetaData
其getter包含this.\u member.tryExportMetadataFormMember(out strs)代码>
tryExportMetadataFormMember(…)
最后有一个检查类型。IsAttributeDefined
查看是否有应用的MetadataAttribute,如问题中的MessageSenderAttribute
任何反馈都将不胜感激。在我最初的问题中,试图理解代码发生了什么,产生了另一个问题:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class MessageSenderAttribute : ExportAttribute
{
public MessageSenderAttribute() : base(typeof(IMessageSender)) { }
public MessageTransport Transport { get; set; }
public bool IsSecure { get; set; }
}
StockTrader RI与中提供的示例之间存在细微差异
在Stocktrader中,定义了ViewExportAttribute
:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
... omitted for brevity ...
}
MEF文件给出了一个类似的例子(同样在原始问题中):
因此,对于上述代码块,区别在于,在第一种情况下,属性来自定义“元数据视图”的接口,而在第二个示例中,情况并非如此;该属性仅具有与IMessageSenderCapabilities
接口相同的属性
“没什么大不了的”你会想,但在StockTrader RI中:
[ImportMany(AllowRecomposition = true)]
public Lazy<object, IViewRegionRegistration>[] RegisteredViews { get; set; }
[ImportMany(AllowRecomposition=true)]
public Lazy[]RegisteredViews{get;set;}
而在MEF示例中:
[ImportMany]
public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }
[ImportMany]
公共延迟[]发送者{get;set;}
因此,这里的区别在于,在Stocktrader RI中,我们尝试延迟导入的类型没有指定(它只是对象),而在第二个示例中,它的定义更具体(IMessageSender)
最终结果大致相同,某些类型随元数据一起延迟导入
然而,我想了解的是:
ViewExportAttribute
专门从IViewRegionRegistration
派生而来,我们可以使用Lazy
[ImportMany]
public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }