继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【.NET 深呼吸】在 .net core app 中使用 Composition

德玛西亚99
关注TA
已关注
手记 410
粉丝 92
获赞 559

.NET 中的 Composition ,即 MEF。MEF 说得简单一点,就是它可以在运行阶段动态地发现类型,用于组件扩展方面特别合适。

.NET Core App 的默认框架并不提供 MEF 有关的 API,但,别忘了 Nuget,那上面有相关的库,而且是官方发布的,不出意外的话,是能用的,而且老周也亲自测过,严重证实是可用的。

哦,是了,顺便提一下,如果你弄的是 ASP.NET Core 项目,对于组件扩展,你可以不必考虑用 Composition,因为 ASP.NET Core 有强大的依赖注入功能,所以,通过注入,也能做到动态发现组件的效果,而且集成性更好。

所以,所以嘛,咱们今天说的 Composition 主要是针对 .net core app,默认模板提供的是控制台应用程序,或者类库。当然了,也可能是其他类型的项目,而且开源项目将来也会多起来。

 

好了,上面说的都是闲话,咱们开始讲正话。

首先,你要先建一个 core 的项目,嗯,就选控制台应用吧。

建好项目之后,打开项目的 Nuget 管理器,搜索:

System.ComponentModel.Composition

注意,别搜错了,因为 System.Composition 是挺多的,能搜出一打来,但是,你要细看,System.ComponentModel.Composition 支持 Core。请注视下面这张高清无码截图。

https://img3.mukewang.com/5b48c68a000187a703730297.jpg

 

现在你明白为啥要选这个了,至于说 System.Composition 是否支持在 .net core app 中使用,这个就不知道了,没试,你有空的话可以试试,但上面没有注明支持 core。

然后安装 System.ComponentModel.Composition 包,安装到项目后,就能用了。来,赶紧试试。

 

引入以下这两个命名空间:

using System.ComponentModel.Composition;using System.ComponentModel.Composition.Hosting;

 

定义一个接口,作为扩展组件的共同协定。

    public interface IMovie
    {        void Play();
    }

它表示某电影院正在上映的电影。

下面两家影院(组件)近期比较热门。

复制代码

    public class NewMovie : IMovie
    {        public void Play()
        {
            Console.WriteLine("此处正在放映《我不是酒神》");
        }
    }    public class NanMovie : IMovie
    {        public void Play()
        {
            Console.WriteLine("此处正在放映《三烤白骨精》");
        }
    }

复制代码

其实这样定义的组件,在运行时还是不能被发现的,我们得让它们导出。方法是……自己看下面代码。

复制代码

    [Export(typeof(IMovie))]    public class NewMovie : IMovie
    {        public void Play()
        {
            Console.WriteLine("此处正在放映《我不是酒神》");
        }
    }    [Export(typeof(IMovie))]    public class NanMovie : IMovie
    {        public void Play()
        {
            Console.WriteLine("此处正在放映《三烤白骨精》");
        }
    }

复制代码

导出约束有这么几种:

* 约束类型,这一般是组件的约定接口,就是组件实现的共同接口,比如上面的 IMovie。

* 约束名,这个嘛,自己赐给它一个名字即可。

* 混合,就是约束名 + 约束类型。这种方法最为准确,在导入时可以准确找到组件。

如果 ExportAttribute 应用的目标是组件类,而不是接口类型,这时你至少得手动指定一个约束类型,设置为 IMovie,不然,它默认就是目标类的名字,这样一来,这两个组件就无法保有共同的约束,导入时不容易找出来。

我为了演示方便,我这些组件的定义与使用都是在同一个程序集中,所以,组件查找范围在当前程序集中。

            // 获取当前程序集
            Assembly assCurr = Assembly.GetExecutingAssembly();            // 确定组件搜索范围
            AssemblyCatalog catalog = new AssemblyCatalog(assCurr);

用上面准备好的 Catalog 去初始化 CompositionContainer ,通过容器去获取发现的组件实例。

            using(CompositionContainer container = new CompositionContainer(catalog))
            {                // 获取已发现的组件
                var components = container.GetExportedValues<IMovie>();            }

GetExportedValues 方法能直接得到所有发现的组件的实例,如果不想马上用到组件实例,可以获取 Lazy 包装的对象,延时初始化,方法是调用 GetExports 或者 GetExport 方法。

得到所有组件实例后,可以尝试调用一下。

复制代码

            using(CompositionContainer container = new CompositionContainer(catalog))
            {                // 获取已发现的组件
                var components = container.GetExportedValues<IMovie>();                // 分别调用一下
                foreach(IMovie m in components)
                {
                    m.Play();
                }            }

复制代码

 

程序运行后,就会输出以下内容。

https://img4.mukewang.com/5b48c69300013af702530094.jpg

 

看,两个组件都被成功调用了。

 

========================================================================

 最近脑细胞不够用,所以博客写得少了,老周在此表示歉意。等过一段时间,脑细胞复活了,老周有空就多写些简单实用的博文。复杂而不实用的东西老周不太会写,唉,没法了,毕竟老周的水平也比较菜,没见过大世面,没做过大项目,没调过大 bug。最大的项目也就是 1213 个实体类,200 多个存储过程,900 多个表,120 个视图。这种规模,估计是老周这一生做过的最大的项目了。

 

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP