Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 了解MEF系统。懒惰<;T、 TMetaData>;_C#_Mvvm_Prism_Mef - Fatal编程技术网

C# 了解MEF系统。懒惰<;T、 TMetaData>;

C# 了解MEF系统。懒惰<;T、 TMetaData>;,c#,mvvm,prism,mef,C#,Mvvm,Prism,Mef,我一直在研究这个系统的内部工作原理 在这个RI中,MEF和一个自定义属性系统被结合使用来注册带有区域的视图,而不是在模块初始值设定项中将内容连接到RegionManager 更具体地说,有一个ViewExportAttribute,它实现: MetaDataAttribute IViewRegion注册 元数据属性和“属性视图”IViewRegionRegistration可由System.Lazy在AutoPopulateExportedViewsBehavior中使用,以实现区域和视图的正确

我一直在研究这个系统的内部工作原理

在这个RI中,MEF和一个自定义属性系统被结合使用来注册带有区域的视图,而不是在模块初始值设定项中将内容连接到RegionManager

更具体地说,有一个
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

  • 因此,这或多或少(非常粗略地)是我们获得导出上的实际元数据的方式,因此,可能通过更多的绕道,这些导出的元数据也将到达Lazy,尽管我仍然无法找到具体的工作方式


    任何反馈都将不胜感激。

    在我最初的问题中,试图理解代码发生了什么,产生了另一个问题:

    [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; }