你的位置:首页 > ASP.net教程

[ASP.net教程]在ServiceStack服务中使用MEF容器


1.ServiceStack服务拥有自身的容器—Funq.Container

当我们使用接口注入的方式调用底层方法时,我们需要在AppHost中重写Configure(Funq.Container container)方法,在方法中添加container.RegisterAutoWiredAs<T, TAs>()配置,才能在服务中使用构造函数注入方式调用接口。代码示例如下:

AppHost.cs:

public class AppHost : AppHostBase  {    public AppHost() //Tell ServiceStack the name and where to find your web services      : base("OAuth2 Demo Resource Server", typeof(UserService).Assembly) { }    public override void Configure(Funq.Container container)    {      //Set JSON web services to return idiomatic JSON camelCase properties      ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;      //Configure User Defined REST Paths      Routes       .Add<Users>("/users")       .Add<Users>("/users/{Username}");      //Register all your dependencies      container.RegisterAutoWiredAs<FakeUserStore, IUserStore>();    }  }

UserService.cs

public class UserService : Service {    private readonly IUserStore userStore;    public UserService(IUserStore userStore) {      this.userStore = userStore;    }    public User Any(Users users) {      if (HttpContext.Current.User.Identity.Name != users.Username) {        throw (new UnauthorizedAccessException(String.Format("Your access token doesn't grant access to information for the user named {0}", users.Username)));      }      return (userStore.GetUser(users.Username));    }  }

缺点:每个接口都需要添加container.RegisterAutoWiredAs<T, TAs>()配置来实例化接口,太过繁琐。

2.ServiceStack服务调用MEF组合容器—CompositionContainer

MEF 提供一种通过“组合”隐式发现组件的方法。 MEF 组件(称为“部件-Part”)。部件以声明方式同时指定其依赖项(称为“导入-Import”)及其提供的功能(称为“导出-Export”)。MEF原理上很简单,找出有共同接口的导入、导出。然后找到把导出的实例化,赋给导入。说到底MEF就是找到合适的类实例化,把它交给导入。

当我们在ServiceStack中调用MEF容器时,我们就可以使用组合容器通过目录搜索组件的定义。步骤如下

2.1 自定义一个IContainerAdapter适配器

 

using ServiceStack.Configuration;using System.ComponentModel.Composition.Hosting;namespace OAuthStack.DataServer.Infrastructure{  internal class MefIOCAdapter : IContainerAdapter  {    private readonly CompositionContainer _container;    internal MefIOCAdapter(CompositionContainer container)    {      _container = container;    }    public T TryResolve<T>()    {      return _container.GetExportedValueOrDefault<T>();    }    public T Resolve<T>()    {      return _container.GetExportedValue<T>();    }  }}

2.在AppHost中重写Configure(Funq.Container container)方法,注册MefIOCAdapter适配器

using OAuthStack.DataServer.Services;using ServiceStack.ServiceInterface.Cors;using ServiceStack.WebHost.Endpoints;using System.ComponentModel.Composition.Hosting;using System.Web.Hosting;namespace OAuthStack.DataServer.Infrastructure{  public class AppHost : AppHostBase  {    public AppHost()      : base("OAuth2 Demo Resource Server", typeof(EquipmentService).Assembly) { }    public override void Configure(Funq.Container container)    {      //Set JSON web services to return idiomatic JSON camelCase properties      ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;      //配置跨域      Plugins.Add(new CorsFeature());      //注册用户认证证书            string directoryName = System.AppDomain.CurrentDomain.BaseDirectory.ToString() + "bin\\";      AggregateCatalog aggregateCatalog = new AggregateCatalog();      if (directoryName != null)      {        //DirectoryCatalog 在指定的目录发现部件。        aggregateCatalog.Catalogs.Add(new DirectoryCatalog(directoryName, "Service*"));
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(directoryName, "Persistance.dll")); } CompositionContainer _mefContainer = new CompositionContainer(aggregateCatalog); container.Adapter = new MefIOCAdapter(_mefContainer); } }}

Service.cs

 public class TService : Service  {    private readonly ITDao _tDao;    [ImportingConstructor]    public TService(ITDao tDao)    {      _tDao = tDao;    }}

优点:无需逐个配置接口实例化,充分利用MEF导入—导出的优点。