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

输出如图:

原文地址:https://www.cnblogs.com/jellochen/p/3665055.html