搜索
热搜: 活动 交友 discuz
查看: 2141|回复: 2
收起左侧

关于C#的MEF简单插件模式简介

[复制链接]
  • TA的每日心情

    2016-1-25 16:08
  • 签到天数: 63 天

    [LV.6]常住居民II

    发表于 2016-1-4 15:05:59 | 显示全部楼层 |阅读模式
    本帖最后由 aNyoNe 于 2016-1-8 17:49 编辑

    什么是MEF
          Managed Extensibility Framework 即 MEF 是用于创建轻量、可扩展应用程序的库。它让应用程序开发人员得以发现和使用扩展且无需配置。它还让扩展开发人员得以轻松地封装代码并避免脆弱的紧密依赖性MEF 让扩展不仅可在应用程序内重复使用,还可以跨程序重复使用。

    扩展问题
           想象你是必须为扩展性提供支持的大型应用程序的设计者。你的应用程序必须包含可能很多的较小组件,且其负责创建和运行较小组件。

           解决问题最简单的方法就是将组件作为源代码包括在你的应用程序并直接从代码中调用它们。这有很多明显缺点。最重要的是,你无法在未调试源代码的情况下添加新组件,这是一项可能被接受的限制(例如在 Web 应用程序中),但不适用于客户端应用程序。同样造成问题的是,你无法访问组件的源代码,因为组件可能由第三方进行了发展,同时由于同样的原因你不能允许第三方访问你的源代码。

           一个稍许复杂的方法为提供扩展点或接口来允许应用程序和组件间的分离。在此模块下,你可能提供组件可实现的接口以及使接口能与应用程序交互使用的 API。这解决了要求源代码访问的问题,但它仍然存在自身问题。

           因为应用程序缺少自行发现组件的能力,所以必须明确对其指出可用且应加载的组件。这通常通过在配置文件中明确记录可用组件来完成。这意味着确保组件正确变成了维护问题,尤其当要求执行更新的人员是最终用户而非开发人员时。

           此外,组件能够与另外的组件进行沟通,除了通过应用程序自身的严格定义的通道。通常不会出现应用程序设计者未预测到特定通信的需求的情况。

           最终,组件开发人员必须接受包含他们实现的接口的程序集所在的硬依赖项。这使得在一个以上的应用程序中使用组件变得困难,且它还会在你创建组件的测试框架时造成问题。


    更多关于MEF的内容介绍


    相关代码展示

    容器类
    [C#] 纯文本查看 复制代码
     public static class ExtendMethod
        {
            public static bool IsNumber(this string str)
            {
                return System.Text.RegularExpressions.Regex.Match(str, @"\d+").Value.Length == str.Length;
            }
    
            /// <summary>
            /// 通过扩展方法装载自身程序集中的MEF控件
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="obj"></param>
            /// <returns>返回装载好控件的类对象</returns>
            public static T ComposePartsSelf<T>(this T obj) where T : class
            {
                var catalog = new AggregateCatalog();
                catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
                //catalog.Catalogs.Add(new DirectoryCatalog("."));
                var _container = new CompositionContainer(catalog);
                _container.ComposeParts(obj);
                return obj;
            }
    
            /// <summary>
            /// 通过扩展方法在指定的路径中装载MEF控件
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="obj"></param>
            /// <param name="path">控件所在的路径</param>
            /// <returns>返回装载好控件的类对象</returns>
            public static T ComposePartsByPath<T>(this T obj, string path) where T : class
            {
                if (!System.IO.Directory.Exists(path))
                    return obj;
                var catalog = new AggregateCatalog();
                catalog.Catalogs.Add(new DirectoryCatalog(path));
                var _container = new CompositionContainer(catalog);
                _container.ComposeParts(obj);
                return obj;
            }
    
            /// <summary>
            /// 通过扩展方法从程序目录的Plugin目录下装载MEF控件
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="obj"></param>
            /// <returns>返回装载好控件的类对象</returns>
            public static T ComposePartsInPlugin<T>(this T obj) where T : class
            {
                return obj.ComposePartsByPath(Environment.CurrentDirectory + "\\Plugin");
            }
        }


    插件装载类
    [C#] 纯文本查看 复制代码
        public class PluginLoader
        {
            [ImportMany]
            public IEnumerable<Lazy<MTInterface.PluginInterface, MTInterface.MetaInterface>> _plugins;
    
            public IEnumerable<Lazy<MTInterface.PluginInterface, MTInterface.MetaInterface>> PluginList { get { return _plugins; } }
    
            public PluginLoader() {
                this.ComposePartsSelf();
                this.ComposePartsInPlugin();
            }
            /// <summary>
            /// 指定控件的路径
            /// </summary>
            /// <param name="path"></param>
            public PluginLoader(string path)
            {
                this.ComposePartsByPath(path);
            }
        }


    欢迎大家下载查看学习,不懂请留言。

    下面是完整程序的Demo。

    游客,如果您要查看本帖隐藏内容请回复













    该用户从未签到

    发表于 2017-9-13 15:13:39 | 显示全部楼层
    不错,值得学习

    该用户从未签到

    发表于 2020-1-5 17:21:14 | 显示全部楼层
    我来打个酱油。
    您需要登录后才可以回帖 登录 | 入住

    本版积分规则

    申请友链| Archiver| 手机版| 鱼·后花园

    GMT+8, 2024-11-21 14:21 , Processed in 0.021122 second(s), 19 queries , Redis On.

    Powered by Discuz! X3.4

    © 2005-2024 鱼·后花园

    快速回复 返回顶部 返回列表