13

如果我想为 ASP.NET MVC 控制器实现依赖注入,我可以使用IControllerFactory接口创建一个工厂类,然后在 Global.asax.cs 中注册它,例如:

ControllerBuilder.Current.SetControllerFactory(controllerFactory)

(参考:http ://www.dotnetcurry.com/ShowArticle.aspx?ID=786 )

现在我的问题是:

如何为IHttpControllerActivator派生类设置工厂?

我们在 ASP.NET MVC 4.0 中是否有类似的东西:

HttpControllerBuilder.Current.SetApiControllerActivator(httpControllerActivator)

?


更新:

我想添加我当前的代码,理解这个案例可能会有所帮助:

我自定义的 HttpControllerActivator:

public class MyCustomApiActivator : DefaultHttpControllerActivator 
                                    //or IHttpControllerActivator ?
{
    private readonly Dictionary<string, Func<HttpRequestMessage, IHttpController>> _apiMap;

    public MyCustomApiActivator(IMyRepository repository)
    {
        if (repository == null)
        {
            throw new ArgumentException("repository");
        }
        _apiMap = new Dictionary<string, Func<HttpRequestMessage, IHttpController>>();
        controllerMap["Home"] = context => new HomeController();
        _apiMap["MyCustomApi"] = context => new MyCustomApiController(repository);
    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        if(_apiMap.ContainsKey(controllerType.Name))
            return _apiMap[controllerType.Name](request);
        return null;
    }
}

我的作文根:

public class CompositionRoot
{
    private readonly IHttpControllerActivator _apiControllerActivator;

    public CompositionRoot()
    {
        _apiControllerActivator = CompositionRoot.CreateHttpControllerActivator();
    }

    public IHttpControllerActivator ApiControllerActivator
    {
        get { return _apiControllerActivator; }
    }

    private static IHttpControllerActivator CreateHttpControllerActivator()
    {
        string defaultRepositoryTypeName = ConfigurationManager.AppSettings["DefaultRepositoryTypeName"];
        var defaultRepositoryType = Type.GetType(defaultRepositoryTypeName, true);
        var defaultRepository = (IMyRepository)Activator.CreateInstance(defaultRepositoryType);

        var apiController = new MyCustomApiActivator(defaultRepository);
        return apiController;
    }
}

最后这是在 my 里面Global.asax.cs,我需要一个技巧:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);


        var root = new CompositionRoot();
        //The following line raise this compile-time error:
        // cannot convert from 'System.Web.Http.Dispatcher.IHttpControllerActivator' 
        //                to 'System.Web.Mvc.IControllerFactory'
        ControllerBuilder.Current.SetControllerFactory(root.ApiControllerActivator);
    }
4

2 回答 2

9

Mark Seemann 是 .NET 中的依赖注入的作者,他有一个关于 DI 和 ASP.NET WebAPI 的简短系列。

他把作曲根放在一个IHttpControllerActivator

  1. 使用 ASP.NET Web API 进行依赖注入和生命周期管理
  2. ASP.NET Web API 中的依赖注入与 Castle Windsor

也许这有帮助。


更新

GlobalConfiguration.Configuration.Services.Replace(
  typeof(IHttpControllerActivator),
  new PoorMansCompositionRoot());

HttpControllerActivator在全球范围内注册您的自定义。

于 2012-10-22T20:52:46.947 回答
1

在 ASP.NET 中,Web APIHttpControllerDispatcher负责构造控制器。默认情况下它与 DependecyResolver 一起使用,但如果你想扩展它的功能,你需要重写它的 SendAsync 方法并重新注册它。

例子:

public class MyCustomDispatcher : HttpControllerDispatcher {

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, 
        CancellationToken cancellationToken) {

        // Do your stuff here

        // According to your requirements, either run its default functionality 
        // or return your own stuff
        return base.SendAsync(request, cancellationToken);
    }
}

笔记:

但是,我无法找到一种优雅的方式来全局替换默认的方式。您可以通过将此自定义调度程序附加到路由来轻松替换每个路由的默认值,但似乎无法在全局范围内执行此操作。我在项目站点上对此进行了讨论:http: //aspnetwebstack.codeplex.com/discussions/400366

于 2012-10-22T19:53:05.147 回答