• Managed Extensibility Framework(MEF) 2 框架新特性介绍


          Managed Extensibility Framework (MEF) 是.NET的一个组合框架,用于增强复杂应用的模块化和可扩展性。从.net framework 4.0 开始集成的组件。到目前为止,MEF的历史上最重要的应用程序是Visual Studio 2010。许多特性都是为了满足Visual Studio里的编辑器的需求,比如说,延迟加载所有东西和细粒度协定。MEF的工作原理简单来看是这样的:

    MEFChart1

    现在 MEF 2.0 版本已集成于.net framework 4.5。 除了以前Import, Export等Attribute,增加的特性包括

    1. 基于约定的编程模型,支持命名约定

    2. 支持泛型

    3. 支持多个范围

    好的,先让我们来看新特性之约定的编程模型,假设这样的简单模型类图:

    GreatEditorD

        public class GreatEditor
        {
            public ILogPlugin Logger { get; set; }
            public ISavePlugin Saver { get; set; }
        }
     
     
        public interface ILogPlugin
        {
            void Write(string message);
        }
     
        public class LoggerPlugin : ILogPlugin
        {
            public void Write(string message)
            {
                Console.WriteLine("Logger {0}", message);
            }
        }
     
        public interface ISavePlugin
        {
            void Save(string message);
        }
        public class FilePlugin : ISavePlugin
        {
            public void Save(string message)
            {
                Console.WriteLine("FilePlugin {0}", message);
     
            }
        }


    上面定义几个简单的Interface,一个名叫GreatEditor客户类引用两个interface,我们通常做法就是在属性实现依赖注入。另请你有注意这里没有使用MEF中的相关Attribute,因为下面我们使用新特性来实现,在代码是这样:

            private static void FluentExportInterfaceDemo()
            {
                Program program = new Program();
                var picker = new RegistrationBuilder();
                picker.ForTypesMatching(pl => pl.Name.EndsWith("Plugin"))
                   .ExportInterfaces();
     
                var catalog = new AssemblyCatalog(typeof(Program).Assembly, picker);
     
                var container = new CompositionContainer(catalog);
                container.ComposeParts(program);
     
                var log = container.GetExportedValue<ILogPlugin>();
                var save = container.GetExportedValue<ISavePlugin>();
     
                save.Save("test");
                log.Write("test");
            } 


    注意首先您需要引用以下namespace:

    using System.Reflection.Context;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Registration;

    类似IOC组件,这里使用命名约定以字符串”Plugin” 结束的Type,Fluent配置风格。然后使用AssemblyCatalog装载Program的Assembly,接着GetExportedValue方法取得我们目前基类型,执行客户方法验证是否是我们想要的结果。

    如果您想Import属性,那是这样的:

            private static void FluentImportPropertiesDemo()
            {
                var picker = new RegistrationBuilder();
                picker.ForTypesDerivedFrom<ILogPlugin>()
                 .Export<ILogPlugin>();
                picker.ForType<GreatEditor>()
                  .Export().ImportProperties<ILogPlugin>(pi => pi.Name == "Logger",
                   (propInfo, builder) =>
                   {
                       builder.AllowRecomposition();
                       builder.RequiredCreationPolicy(CreationPolicy.NonShared);
                   });
     
     
                var catalog = new AssemblyCatalog(typeof(Program).Assembly, picker);
                var container = new CompositionContainer(catalog);
                container.Compose(new CompositionBatch());
                var editor = container.GetExportedValue<GreatEditor>();
     
                editor.Logger.Write("Let it go");
            } 


    如果想ExportMany类型,这里我们使用.net framwork自带加密类做演示:

        [Export]
        public class AlgorithmCollection
        {
            [ImportMany]
            public SymmetricAlgorithm[] CryptoProviders { get; private set; }
        }
     
        public class CryptoComposer
        {
            public SymmetricAlgorithm Aes { get { return new AesManaged(); } }
            public SymmetricAlgorithm TripleDES { get { return new TripleDESCryptoServiceProvider(); } }
            public SymmetricAlgorithm RC2 { get { return new RC2CryptoServiceProvider(); } }
        }


    看到上面标记ImportMany的Attribute, 对应这里是SymmetricAlgorithm  Array类型,接着 调用方法如下:

            private static void FluentMultiExportPropertiesDemo()
            {
                var picker = new RegistrationBuilder();
                picker.ForType<CryptoComposer>()
                  .ExportProperties(p => p.PropertyType == typeof(SymmetricAlgorithm));
     
                var catalog = new AssemblyCatalog(typeof(Program).Assembly, picker);
                var container = new CompositionContainer(catalog);
     
                var foo = container.GetExportedValue<AlgorithmCollection>();
     
                //output for debug
                foo.CryptoProviders.ToList().ForEach(pr => Console.WriteLine(pr));
     
            } 


    还有构造器Import的情况,假设有这样的Model:

    Wokerd

        public interface ILogger
        {
            void Write(string message);
        }
     
        public class Logger : ILogger
        {
            public void Write(string message) {
                Console.WriteLine("Log with console : {0}", message);
            }
        }
     
        public class Worker
        {
            private ILogger _logger;
     
            public Worker(){}
     
            public Worker(ILogger logger)
            {
                _logger = logger;
            }
     
            public void Execute(string message)
            {
                _logger.Write(message);
            }
        }

    注意上面Work有一个有参的构造方法,调用的代码是这样的:

            private static void FluentImportConstructorDemo()
            {
                var picker = new RegistrationBuilder();
                picker.ForTypesDerivedFrom<ILogger>()
                 .Export<ILogger>();
                picker.ForType<Worker>()
                    .SelectConstructor(ctors => ctors.First(info => info.GetParameters().Length == 1))
                   .Export();
     
                var catalog = new AssemblyCatalog(typeof(Program).Assembly, picker);
                var container = new CompositionContainer(catalog);
                container.Compose(new CompositionBatch());
                var worker = container.GetExportedValue<Worker>();
     
                worker.Execute("Let it go");
            } 
     

    上面的代码有注意使用SelectConstructor方法,选择有参数的构造器。
    最后对于泛型的支持例子是这样的:

        public class FooWithOpenGeneric
        {
            [Import]
            public EventAggregator<int> IntAggregator { get; set; }
        }
     
        [Export]
        public class EventAggregator<T>
        {
            public event Action<T> Notify = (item) => { };
            public void Send(T item)
            {
                Notify(item);
            }
        }


    如果了解泛型Generic不难看懂,调用代码:

            private static void WorkWithOpenGeneric()
            {
                var picker = new RegistrationBuilder();
                picker.ForType<FooWithOpenGeneric>()
                 .Export();
     
                var catalog = new AssemblyCatalog(typeof(Program).Assembly, picker);
                var container = new CompositionContainer(catalog);
                container.Compose(new CompositionBatch());
                var fooWithOpenGeneric = container.GetExportedValue<FooWithOpenGeneric>();
            } 


    全部Demo方法合并在一起测试下:

            static void Main(string[] args)
            {
                WorkWithOpenGeneric();
                FluentImportConstructorDemo();
                FluentExportInterfaceDemo();
                FluentImportPropertiesDemo();
                FluentMultiExportPropertiesDemo();
                Console.Read();
            }


    通过上面代码演示,对MEF 2.0的两个新特性有一定了解吧,代码在 Visual Studio 2012, .net framework 4.5 测式通过。MEF在实际开发做为轻量级的组件实现基于Plugin开发,使得你的程序具有可扩展性,重用性。关于MEF更详细的内容可参考MSDN.  MEF 2 实现了Plugin模式,最难得是现在集成于 .net framework 4.5 中,它还有一个子集版本支持Win 8 Metro App开发。

    你可参感兴趣文章:

    Pluge模式
    使用Fluent配置API驱动Enterprise Library 5.0
    EneterpriseLibrary5的Fluent配制API


    作者:Petter Liu
    出处:http://www.cnblogs.com/wintersun/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    该文章也同时发布在我的独立博客中-Petter Liu Blog

  • 相关阅读:
    tomcat剖析(一)
    java内存区域
    经典排序算法-冒泡与选择
    使用docker安装mysql服务
    C语言博客作业--结构体
    C博客作业--指针
    C语言博客作业--字符数组
    C语言博客作业--数组
    C语言博客作业--数据类型
    C语言博客作业--函数
  • 原文地址:https://www.cnblogs.com/wintersun/p/2863405.html
Copyright © 2020-2023  润新知