zoukankan      html  css  js  c++  java
  • MEF 插件式开发之 DotNetCore 初体验

    背景叙述

    在传统的基于 .Net Framework 框架下进行的 MEF 开发,大多是使用 MEF 1,对应的命名空间是 System.ComponentModel.Composition。在 DotNet Core 中,微软为了伟大的跨平台策略,引入了 MEF 2,其对应的命名空间是 System.Composition,这个需要开发者自己在 Nuget 上进行下载安装 Microsoft.Composition。2 与 1 相比,无论是在支持平台上还是性能上都有改进,值得我们探讨一下。

    动手实验

    实验1:在 DotNetCore 控制台程序中尝试使用 MEF2

    首先,我们创建一个 DotNet Core 控制台应用程序,然后为其添加 MEF2 对应的 Package:Microsoft.Composition;

    然后,我们创建一个示例接口:

    public interface IMessageSender
    {
        void Send(string message);
    }
    

    接着,我们再创建一个示例类来实现该接口,并尝试将其导出:

    [Export(typeof(IMessageSender))]
    public class EmailSender : IMessageSender
    {
        public void Send(string message)
        {
            Console.WriteLine(message);
        }
    }
    

    最后,我们在主程序中进行调用:

    class Program
    {
        static void Main(string[] args)
        {
            //寻找主程序命名空间
            var assembiles = new[] { typeof(Program).GetTypeInfo().Assembly };
    
            //配置 MEF 容器
            var configuration = new ContainerConfiguration()
                .WithAssembly(typeof(Program).GetTypeInfo().Assembly);
            using (var container = configuration.CreateContainer())
            {
                //依据相应接口获取导出的具体类
                IMessageSender messageSender = container.GetExport<IMessageSender>();
    
                messageSender.Send("Hello MEF2");
            }
            Console.ReadKey();
        }
    }
    

    此时,如果一切正常的话,程序会输入如下结果:

    实验2:在 DotNetCore 控制台程序中尝试使用 MEF2 加载外部组件

    由于微软在 DotNetCore 中为开发者提供了新的程序集加载方式 AssemblyLoadContext。它允许多次加载相同的程序集,并创建相互独立的副本,并且它比 AppDomain 重量轻得多。因此我在本次实验中,笔者尝试使用这种新的加载方式进行实验。

    首先,我们创建一个如下图所示的解决方案:

    • DotNetCoreMEF:控制台程序,安装 Microsoft.Composition,并引用 DotNetCoreMEF.Core
    • DotNetCoreMEF.Core:核心类库,用于定义相关接口;
    • DotNetCoreMEF.Plugin1:插件类库,安装 Microsoft.Composition,并引用 DotNetCoreMEF.Core
    • DotNetCoreMEF.Plugin2:插件类库,安装 Microsoft.Composition,并引用 DotNetCoreMEF.Core

    注意:请确保上述项目的生成目录保持一致。

    相关示例代码如下所示:

    IMessageSender.cs

    public interface IMessageSender
    {
        void Send(string message);
    }
    

    EmailSender.cs

    [Export(typeof(IMessageSender))]
    public class EmailSender : IMessageSender
    {
        public void Send(string message)
        {
            Console.WriteLine($"Email:{message}");
        }
    }
    

    SMSSender.cs

    [Export(typeof(IMessageSender))]
    public class SMSSender : IMessageSender
    {
        public void Send(string message)
        {
            Console.WriteLine($"SMS:{message}");
        }
    }
    

    Program.cs

    class Program
    {
        static void Main(string[] args)
        {
            var assembiles = Directory.GetFiles(AppContext.BaseDirectory, "*.dll", SearchOption.TopDirectoryOnly)
                .Select(AssemblyLoadContext.Default.LoadFromAssemblyPath);
    
            var conventions = new ConventionBuilder();
            conventions.ForTypesDerivedFrom<IMessageSender>()
                .Export<IMessageSender>()
                .Shared();
    
            var configuration = new ContainerConfiguration()
                .WithAssemblies(assembiles, conventions);
    
            using (var container = configuration.CreateContainer())
            {
                IEnumerable<IMessageSender> senders = container.GetExports<IMessageSender>();
                foreach (var sender in senders)
                {
                    sender.Send("Hello World");
                }
            }
    
            Console.ReadKey();
        }
    }
    

    此时,我们将项目全部重新编译一下,可通过 VS 调试运行,看到相应的输出结果。当然,我们也可以通过命令行的方式运行程序,前提是我们需要将我们的程序发布一下。发布好后我们可以执行 dotnet DotNetCoreMEF.dll 看到输出结果:

    总结

    上述展示的只是 MEF 在 DotNet Core 中的简单应用,其中需要注意的是 AssemblyLoadContext ,此外,关于模块的 延迟记载元数据的获取 ,感兴趣的朋友可参考我之前的一篇博客进行参考:MEF 插件式开发 - WPF 初体验

    其实,如果对 DotNet Core 有一定了解的朋友是知道的,上述这种方式虽然实现了插件式的开发模式,但是并没有完全发挥 DotNet Core 本身所具有优势:内置 DI。所以,我们完全可以使用更高效的方式来实现。在下篇博客中,我们将感受一下 DotNet Core 中强大的 DI 。

    相关参考

  • 相关阅读:
    新浪微盘又是一个给力的产品啊,
    InfoQ: 百度数据库架构演变与设计
    列式数据库——Sybase IQ
    MapR初体验 淘宝共享数据平台 tbdata.org
    IBM正式发布新一代zEnterprise大型机(组图) 大型机,IBM,BladeCenter,美国,纽约 TechWeb News
    1TB is equal to the number of how many GB? 1PB equal to is equal to the number of TB? 1EB PB? | PCfault.com
    Cassandra vs HBase | WhyNosql
    The Hadoop Community Effect
    雅虎剥离开源软件平台 Hadoop ,与风投新建 Hortonworks 公司 品味雅虎
    RowOriented Database 、ColumnOriented Database 、KeyValue Store Database 、DocumentOriented Database
  • 原文地址:https://www.cnblogs.com/hippieZhou/p/9451950.html
Copyright © 2011-2022 走看看