簡體   English   中英

使用unity容器將對象注入控制器的構造函數

[英]Inject object to the constructor of controller using 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和向后,准備給定組件的數據源等。

@Razem,您對我的評論的猜測是正確的。 你描述的負點也是有效的。

您所要求的“服務取決於控制器”肯定可以實現,但這將是一個糟糕的設計。

目前, BaseClass僅依賴於TempController 當您需要其他控制器中的BaseClass時,您將如何處理該場景? 代碼將開始破解,您將最終向BaseClass添加新的依賴項。

另外根據設計建議,頂層應該依賴於底層而不是反之亦然。

話雖如此,通過使控制器依賴於IBaseClass ,您仍然可以實現您正在尋找的功能。

我不確定您在BaseClass訪問控制器所需的具體原因。 在創建以下建議時我做了一些假設。 其中一個假設是BaseClassIBaseClassController類是同一個程序集的一部分。

//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創建一個方法,為它設置Controller。

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

並從中獲得TempControllerBaseController ,並使其依賴於IBaseClass 並在構造函數中TempController調用SetController的方法IBaseClass通過傳遞this參數了。 您還可以在此處覆蓋BaseController方法/屬性。

在此之后,您可以調用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();
    }
}

在您的Web項目中安裝nuget包Unit.Mvc 打開文件Unity.Config位於下App_Start文件夾及更換方法RegisterTypes如下。

public static void RegisterTypes(IUnityContainer container)
{
   container.RegisterType<IBaseClass, BaseClass>(new PerRequestLifetimeManager());
}

我相信我不需要解釋這是如何起作用的。

PS:您需要確保在控制器構造函數中調用IBaseClass.SetController方法,以避免在BaseClass使用控制器時出現NullReferenceException。 這是您需要采取的小開銷,以實現良好和可維護的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM