使用unity容器将对象注入控制器的构造函数

时间:2017-03-10 22:31:15

标签: c# asp.net-mvc unity-container

我找不到任何类似的问题,所以我写这篇文章。有私有字段IBaseClass的样本控制器。示例代码如下所示:

public class TmpController : Controller
    {
        private IBaseClass _baseClass;

        public TmpController()
        {
            _baseClass = new BaseClass(this);
        }   
    }

    public interface IBaseClass
    {
        //...
    }

    public class BaseClass : IBaseClass
    {
        protected TmpController TmpController;

        public BaseClass(TmpController tmpController)
        {
            TmpController = tmpController;
        }

        //IBaseClass implementation
    }

我的问题是;如何使用Unity框架将BaseClass对象注入到TmpController的构造函数中? 我想让我的控制器"更苗条"。我想把关于验证的逻辑和准备我的控件的数据源(如comboBox等)放到不同的类中。我尝试在我的.Web项目中使用某种特定情况制作某种SOC,这将使我的控制器更易于阅读和维护。我每个视图使用一个控制器,但我遇到了非常复杂的形式。目前我有超过3000行代码的控制器,并且很难维护,所以我想用它做一些事情。 是的,我使用的是服务和存储库,但问题在于验证ViewModel,将ViewModel对象映射到DTO和向后,准备给定组件的数据源等。

1 个答案:

答案 0 :(得分:0)

@Razem,您对我的评论的猜测是正确的。你描述的负点也是有效的。

您所问的“服务取决于控制器”肯定可以实现,但这将是一个糟糕的设计。

目前import mechanize br = mechanize.Browser() br.open("website") 仅依赖于BaseClass。当您需要其他控制器中的TempController时,您将如何处理该场景?代码将开始中断,您最终会向BaseClass添加新的依赖项。

同样根据设计建议,顶层应该依赖于底层而不是反之亦然。

话虽如此,通过使控制器依赖于BaseClass,您仍然可以实现您正在寻找的功能。

我不确定您在IBaseClass内访问控制器所需的具体原因。在创建以下建议时我做了一些假设。其中一个假设是BaseClassBaseClassIBaseClass类属于同一个程序集。

Controller

//Have a BaseController Class with the properties and/or method which you will be using in the `BaseClass` class and make them virtual so that derived controller classes can override them to have specific implementation. public class BaseController : Controller { public virtual string ControllerMethod() { return "Controller Method from Base Controller"; } public virtual string RandomValue { get { return "Random value from Base Controller"; } } } 中创建一个方法,为其设置控制器。

IBaseClass

public interface IBaseClass { void SetController(BaseController controller); void Method1(); } public class BaseClass : IBaseClass { private BaseController controller; public void SetController(BaseController controller) { this.controller = controller; } public void Method1() { var str = this.controller.RandomValue; } } 派生TempController并使其依赖于BaseController。在IBaseClass {@ 1}} TempController方法的构造函数中,通过SetController参数传递给它。您还可以在此处覆盖IBaseClass的方法/属性。

在此之后,您可以调用this的任何方法,而无需将控制器实例传递给它。

BaseController

在您的网络项目中安装nuget包 Unit.Mvc 。打开位于 App_Start 文件夹下的文件IBaseClass,然后更改方法public class TempController : BaseController { private IBaseClass baseClass; public HomeController(IBaseClass productService) { this.baseClass = productService; this.baseClass.SetController(this); } public override string RandomValue { get { return "Random value from Derived Class."; } } public ActionResult Index() { this.baseClass.Method1(); ViewBag.Title = "Home Page"; return View(); } } ,如下所示。

Unity.Config

我确信我不需要解释它是如何起作用的。

P.S。 :您需要确保在控制器构造函数中调用RegisterTypes方法,以避免在public static void RegisterTypes(IUnityContainer container) { container.RegisterType<IBaseClass, BaseClass>(new PerRequestLifetimeManager()); } 中使用控制器时出现NullReferenceException。这是您需要采取的小开销,以实现良好和可维护的设计。