• MEF初体验之八:过滤目录


    当在使用子容器的时候,基于某些具体标准来过滤目录可能是重要的。例如,基于部件的创建策略来过滤是很常见的。下面的代码片段演示了如何构建这种特别方法:

    var catalog = new AssemblyCatalog(typeof(Program).Assembly);
    var parent = new CompositionContainer(catalog);
    
    var filteredCat = new FilteredCatalog(catalog,
        def => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) &&
        ((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) == CreationPolicy.NonShared);
    var child = new CompositionContainer(filteredCat, parent);
    
    var root = child.GetExportedObject<Root>();
    child.Dispose();

    如果CreationPolicy还足以作为一个标准来选择部件的话,你或许想使用[PartMetadata]来代替。它允许你附加元数据在部件上,因此你可以使用它来构建一个过滤表达式。例如,下面是一个应用该特性的类:

    [PartMetadata("scope", "webrequest"), Export]
    public class HomeController : Controller
    {
    } 

    这使你可以用那些应该被限定到一个(逻辑)web请求的部件来创建子容器。注意它由你来定义一个范围边界,换句话说,MEF并不知道"webrequest"是什么,因此,你必须在每次web请求时建立一些基础设施代码来创建/释放容器。

    var catalog = new AssemblyCatalog(typeof(Program).Assembly);
    var parent = new CompositionContainer(catalog);
    
    var filteredCat = new FilteredCatalog(catalog,
        def => def.Metadata.ContainsKey("scope") &&
        def.Metadata["scope"].ToString() == "webrequest");
    var perRequest = new CompositionContainer(filteredCat, parent);
    
    var controller = perRequest.GetExportedObject<HomeController>();
    perRequest.Dispose();

    注意:我们没有提供FilteredCatalog类。下面我们将拿一个简单的实现来说明创建FilteredCatalog:

    using System;
    using System.ComponentModel.Composition.Primitives;
    using System.ComponentModel.Composition.Hosting;
    using System.Linq;
    using System.Linq.Expressions;
    
    public class FilteredCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged
    {
        private readonly ComposablePartCatalog _inner;
        private readonly INotifyComposablePartCatalogChanged _innerNotifyChange;
        private readonly IQueryable<ComposablePartDefinition> _partsQuery;
    
        public FilteredCatalog(ComposablePartCatalog inner,
                               Expression<Func<ComposablePartDefinition, bool>> expression)
        {
            _inner = inner;
            _innerNotifyChange = inner as INotifyComposablePartCatalogChanged;
            _partsQuery = inner.Parts.Where(expression);
        }
    
        public override IQueryable<ComposablePartDefinition> Parts
        {
            get
            {
                return _partsQuery;
            }
        }
    
        public event EventHandler<ComposablePartCatalogChangeEventArgs> Changed
        {
            add
            {
                if (_innerNotifyChange != null)
                    _innerNotifyChange.Changed += value;
            }
            remove
            {
                if (_innerNotifyChange != null)
                    _innerNotifyChange.Changed -= value;
            }
        }
    
        public event EventHandler<ComposablePartCatalogChangeEventArgs> Changing
        {
            add
            {
                if (_innerNotifyChange != null)
                    _innerNotifyChange.Changing += value;
            }
            remove
            {
                if (_innerNotifyChange != null)
                    _innerNotifyChange.Changing -= value;
            }
        }
    }

    最后举个简单例子:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace FilteringCatalogsSample
    {
        class Program
        {
            [ImportMany]
            public IEnumerable<IMessageSender> Senders { get; set; }
            static void Main(string[] args)
            {
                Program p = new Program();
                p.Compose();
                foreach (var item in p.Senders)
                {
                    item.Send("Hi,MEF");
                }
                Console.ReadKey();
            }
            void Compose()
            {
                var catalog = new AssemblyCatalog(typeof(Program).Assembly);
                var parent = new CompositionContainer(catalog);
                var filterCatalog = new FilteredCatalog(catalog,
                    def => def.Metadata.ContainsKey("methods")
                    && def.Metadata["methods"].ToString() == "sms");
                //var AggrContainer = new CompositionContainer(filterCatalog, parent);
                var child = new CompositionContainer(filterCatalog);
                child.ComposeParts(this);
            }
        }
        interface IMessageSender
        {
            void Send(string msg);
        }
        [Export(typeof(IMessageSender))]
        public class EmailSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("Email sent:" + msg);
            }
        }
        [Export(typeof(IMessageSender))]
        public class SecureEmailSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("Secure Email sent:" + msg);
            }
        }
        [Export(typeof(IMessageSender))]
        [PartMetadata("methods","sms")]
        public class SMSSender : IMessageSender
        {
            public void Send(string msg)
            {
                Console.WriteLine("SMS sent:" + msg);
            }
        }
    }

    输出如图:

  • 相关阅读:
    启动时间知多少?8款音视频类应用测评报告分析
    优化信息流很麻烦?三招教你轻松搞定
    vmstat
    iostat
    dstat
    strace
    Mysql(一)
    rsync
    Kubernetes-深入分析集群安全机制
    Kubernetes-apiserver
  • 原文地址:https://www.cnblogs.com/jellochen/p/3665055.html
Copyright © 2020-2023  润新知