简体   繁体   English

MVC控制器使用AutoFac进行通用注入

[英]MVC Controller Generic injection with AutoFac

I am fairly new to DI with Autofac and wonder if the following is possible 我对使用Autofac的DI相当新,并想知道以下是否可行

I want to create a generic controller and action that receives an injected type. 我想创建一个接收注入类型的通用控制器和动作。 I do not want an instance of the injected type, but just need its type, which would be an inplementation of an expected interface. 我不想要一个注入类型的实例,但只需要它的类型,这将是一个预期接口的实现。

I would also like to pass that generic type on to a ViewModel, but that is another subject altogether, however if some genious out there can solve both that would be excellent. 我也想把这个泛型类型传递给ViewModel,但这完全是另一个主题,但是如果有一些天才可以解决这两个问题,那将是非常好的。

public ContractorController<T> : Controller 
    where T : IContractor{ 

    public ViewResult New() { 
            var vNewModel = new NewViewModel<T>(); 
            return View(vNewModel); 
        } 
} 

This controller should be called through http://mysite.com/Contractor/New 应通过http://mysite.com/Contractor/New调用此控制器

I have been looking into registering generics with AutoFac, but it seems that the problem is that the AutofacControllerFactory only implements GetControllerInstance(), expecting the controller Type passed to it from either GetController() or CreateController(), not sure which or what the diffirence is between them. 我一直在寻找使用AutoFac注册泛型,但似乎问题是AutofacControllerFactory只实现了GetControllerInstance(),期望从GetController()或CreateController()传递给它的控制器类型,不确定哪个或哪个不同在他们之间。 These methods receive the controller's name as a string from RoutData and return the corresponding .NET type which, give the url, http://mysite.com/Contractor/New is controller=Contractor and thus ContractorController cannot be matched by GetController() or CreateController() and therfore passing null to GetControllerInstance() which mean AutofacControllerFactory does not attempt to resolve the type. 这些方法从RoutData接收控制器的名称作为字符串,并返回相应的.NET类型,给出URL, http://mysite.com/Contractor/New ://mysite.com/Contractor/New是controller = Contractor,因此ContractorController不能与GetController()匹配或CreateController()和therfore将null传递给GetControllerInstance(),这意味着AutofacControllerFactory不会尝试解析该类型。

I figured that I would have to create a custom Controller Factory deriving from AutofacControllerFactory, override GetController() or CreateController() and perform my own mapping from the controller names to the generic types. 我想我必须创建一个派生自AutofacControllerFactory的自定义Controller Factory,重写GetController()或CreateController()并执行我自己的映射,从控制器名称到泛型类型。 Something like 就像是

if (controllerName == "Contractor") return System.Type.GetType( "UI.Controllers." + controllerName + "Controller`1"); if(controllerName ==“Contractor”)返回System.Type.GetType(“UI.Controllers。”+ controllerName +“Controller`1”);

When I debug this I can see that this code is finding the generic controller and returning it. 当我调试这个时,我可以看到这个代码正在找到通用控制器并返回它。

I thought I could then just register the types like 我想我可以只注册类似的类型

builder.RegisterType<FakeContractor>().As<IContractor>(); 
builder.RegisterGeneric(typeof(ContractorController<>)); 

But I am getting the following error 但是我收到以下错误

The Autofac service 
'UI.Controllers.ContractorController`1' 
representing controller 
'ContractorManagement.UI.Controllers.ContractorController`1' 
in path '/Contractor/New' has not been registered. 

So I think I may be barking up the wrong tree. 所以我想我可能正在咆哮错误的树。 Can anyone please shed some light on how I can do this without pulling my teeth 任何人都可以在没有拔牙的情况下阐明如何做到这一点

Thank you 谢谢

I'm not entirely sure why you want a controller using a generic. 我不完全确定你为什么要使用通用的控制器。 Using a generic on a Controller isn't really supported in Mvc - or at least the supporting routing path would be involved. 在Mvc中实际上不支持在Controller上使用通用 - 或者至少涉及支持路由路径。 Perhaps you can provide more info on the reasoning behind the approach? 也许您可以提供有关该方法背后原因的更多信息?

What it looks like is that you want a controller that supports model binding against varying types. 它看起来像是你想要一个支持不同类型的模型绑定的控制器。 The next question is whether these types vary across a common interface or base class. 接下来的问题是这些类型是否在公共接口或基类之间有所不同。

If that's the case, for Mvc2 check out the IocModelBinder information . 如果是这种情况,对于Mvc2,请查看IocModelBinder信息 This will work with Autofac quite well. 这将非常适合Autofac。 This will allow the type to be model bound on post or get allowing you to inject services with autofac. 这将允许类型在post或get上进行模型绑定,允许您使用autofac注入服务。

If you want to vary the types by a common base - supporting a variety of concrete view model - then check out the DerivedTypeModelBinder in MvcContrib . 如果您想通过一个共同的基础来改变类型 - 支持各种具体的视图模型 - 那么请查看MvcContrib中的DerivedTypeModelBinder There is a version that works in Mvc 1, 2 and now MvcContrib for Mvc3 has a good sample app to accompany it. 有一个版本适用于Mvc 1,2,现在MvcContrib for Mvc3有一个很好的示例应用程序。 The Mvc3 implementation is also faster - speed wasn't a problem before, it's just a more efficient identification process. Mvc3实现也更快 - 速度以前不是问题,它只是一个更有效的识别过程。

Maybe it's not a direct answer to your question, but this is the only possible way to use generic controllers that I ever seen and used: 也许这不是你问题的直接答案,但这是使用我见过和使用的通用控制器的唯一可行方法:

public abstract class ContractorControllerBase<T> : Controller where T : IContractor { 
    public ViewResult New() { 
        var vNewModel = new NewViewModel<T>(); 
        return View(vNewModel); 
    } 
} 

public class FakeContractorController : ContractorControllerBase<FakeContractor> {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM