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

发布于 2024-10-12 16:35:39 字数 1670 浏览 3 评论 0原文

我对 Autofac 的 DI 相当陌生,想知道以下是否可能

我想创建一个通用控制器和接收 注射型。 我不需要注入类型的实例,但只需要它 类型,这将是预期接口的实现。

我还想将该泛型类型传递给 ViewModel,但这完全是另一个主题,但是如果有一些天才可以解决这两个问题,那就太好了。

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

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

该控制器应该通过调用 http://mysite.com/Contractor/New

我一直在考虑使用 AutoFac 注册泛型,但它 似乎问题在于 AutofacControllerFactory 仅实现 GetControllerInstance(),期望从 GetController() 或 CreateController() 传递给它的控制器类型,不确定它们之间有什么区别。这些方法从 RoutData 接收控制器名称作为字符串,并返回相应的 .NET 类型,给定 url,http://mysite.com/Contractor/New 是controller=Contractor,因此 ContractorController 不能由 GetController() 或 CreateController() 匹配,因此将 null 传递给 GetControllerInstance() 这意味着 AutofacControllerFactory 不会尝试解析该类型。

我想我必须创建一个自定义控制器工厂 从 AutofacControllerFactory 派生,重写 GetController() 或 CreateController() 并 执行我自己的从控制器名称到通用类型的映射。 类似于

if (controllerName == "Contractor") 返回 System.Type.GetType( “UI.控制器。” + 控制器名称 + "控制器`1");

当我调试它时,我可以看到该代码正在查找通用控制器并返回它。

我想我可以只注册类似的类型

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

但是我收到以下错误

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

所以我想我可能找错了树。 谁能告诉我如何在不拉扯的情况下做到这一点 我的牙齿

谢谢你

I am fairly new to DI with Autofac and wonder if the following is possible

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.

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

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. 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.

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.
Something like

if (controllerName == "Contractor")
return 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淡淡绿茶香 2024-10-19 16:35:39

我不完全确定为什么你想要一个使用通用的控制器。 Mvc 中并不真正支持在控制器上使用泛型 - 或者至少会涉及支持路由路径。也许您可以提供有关该方法背后的推理的更多信息?

看起来您需要一个支持针对不同类型的模型绑定的控制器。下一个问题是这些类型在公共接口或基类中是否有所不同。

如果是这种情况,对于 Mvc2,请查看 IocModelBinder 信息。这与 Autofac 配合得很好。这将允许类型在 post 上进行模型绑定,或者允许您使用 autofac 注入服务。

如果您想通过通用基础来改变类型 - 支持各种具体视图模型 - 那么请查看 MvcContrib 中的 DerivedTypeModelBinder。有一个适用于 Mvc 1、2 的版本,现在 MvcContrib for Mvc3 有一个很好的示例应用程序来配合它。 Mvc3 实现也更快 - 速度以前不是问题,它只是一个更高效的识别过程。

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. 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. This will work with Autofac quite well. This will allow the type to be model bound on post or get allowing you to inject services with 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. There is a version that works in Mvc 1, 2 and now MvcContrib for Mvc3 has a good sample app to accompany it. The Mvc3 implementation is also faster - speed wasn't a problem before, it's just a more efficient identification process.

破晓 2024-10-19 16:35:39

也许这不是对你的问题的直接答案,但这是使用我见过和使用过的通用控制器的唯一可能的方法:

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> {
}

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> {
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文