MEF接口应用初探

Managed Extensibility Framework (MEF)

关于MEF可参看官方文档http://msdn.microsoft.com/zh-cn/library/dd460648.aspx

本文旨在将MEF应用到普通接口框架内部,构造可插拔,易扩展的接口框架。MEF还有很多其他应用(MVC,Winform)可以构建插件式,可持续的应用

DEMO

1.项目结构

2.核心接口

接口定义一个方法名,以及请求内容参数

public interface IService
    {
        String GetResponse(string method, String input);
    }

  接口实现:

[Export(typeof(IService))]//导出该实现(有导出那肯定有导入,在需要用到的地方导入即可)
    public class MyService : IService
    {
        [ImportMany]
        IEnumerable<Lazy<IOperation, IOperationData>> operations;//导入部件集合(各个对外接口)
        public String GetResponse(string method, String input)
        {
            try
            {
                foreach (Lazy<IOperation, IOperationData> i in operations)
                {
                    if (i.Metadata.Method.Equals(method)) return i.Value.Operate(input).ToString();
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return "内部异常";
        }
    }

  其中 IOperation,与IOperationData两个接口是各个对外接口部件的契约,实现如下(各个对外接口部件都要实现这两个接口)

public interface IOperation
    {
        String Operate(String req);
    }
public interface IOperationData
    {
        String Method { get; }
    }

2.部件组装

我将组装步骤放在了应用程序启动时,并且定义静态变量缓存无需每次请求都进行组装

public class OnStart
    {
        public static CompositionContainer _container;//静态部件容器,最常用容器
        [Import(typeof(IService))]//此处需要使用到之前定义的接口所以导入
        public IService service;

        public static IService Service { get; set; }//静态
        public OnStart()
        {
            if (Service == null)
            {
                //一个可变集合目录包含多个部件
                var catalog = new AggregateCatalog();
                //从同一个程序集内加载部件
                //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
                //从文件夹加载部件
                DirectoryInfo di = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Apis"));
                DirectoryInfo[] dis = di.GetDirectories("Service*", SearchOption.TopDirectoryOnly);
                foreach (DirectoryInfo item in dis)
                {
                    catalog.Catalogs.Add(new DirectoryCatalog(item.FullName));//从以Service开头的文件夹中加载各个部件(我将每个部件通过单独的文件夹独立)
                }
          
                catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyService).Assembly));//主部件
                //catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
               // _container.ComposeExportedValue<IService>(new MyService());
                //catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Apis")));
                //创建部件容器(CompositionContainer最常用)
                _container = new CompositionContainer(catalog);
                // _container.SatisfyImportsOnce()
                //Fill the imports of this object
                try
                {
                    //在容器中组合部件
                    _container.ComposeParts(this);
                }
                catch (CompositionException compositionException)
                {
                    throw;
                }
            }
            Service = service;
        }
    }
3.客户端调用
各个部件都组装好后,调用则非常简单,只有一行代码
public class Client
    {
        public static string Excute(string service,string request)
        {
            return OnStart.Service.GetResponse(service, request);
        }
    }

4.部件开发

新建新的类库项目,定义一个Query类,

[Export(typeof(IOperation))]
    [ExportMetadata("Method", "query")]
    public class Query : IOperation
    {
        public String Operate(String req)
        {
            return req + "查询";
        }
    }

右击属性设置一下生成事件

copy "$(TargetDir)" "$(SolutionDir)MefApiApisService2"

这样一个部件就开发完成

5.Host

我通过一个简单的Web(Nancy框架)部署该接口(也可使用控制台,OWin等)

代码如下

public class HostModule : Nancy.NancyModule
    {
        public HostModule()
        {
            After.AddItemToEndOfPipeline(t =>
            {
                t.Response.WithContentType("application/json; charset=utf-8");
            });
       //Post请求
            Post["/{Service}"] = p =>
            {
                try
                {
                    string service = p.Service.ToString().ToLower().Trim();
                    string request = string.Empty;
                    using (StreamReader sr = new StreamReader(Request.Body))
                    {
                        request = sr.ReadToEnd();
                    }
                    return Client.Excute(service, request);
                }
                catch (Exception ex)
                {
                    return Response.AsJson(new { result = false, msg = ex.Message });
                }
            };
       //Get请求 Get[
"/{Service}"] = p => { try { string service = p.Service.ToString().ToLower().Trim(); string request = Request.Query["request"]; return Client.Excute(service, request); } catch (Exception ex) { return Response.AsJson(new { result = false, msg = ex.Message }); } }; } }

6.结果

http://localhost:9803/query?request=asdfasdf

DEMO

代码不优,研究学习用0.0

原文地址:https://www.cnblogs.com/isingel/p/3968134.html