簡體   English   中英

控制/依賴注入和轉換運算符的反轉

[英]Inversion of Control / Dependency Injection and conversion operators

我有許多MVC應用程序使用的UserModel類,我正在嘗試轉換為使用IoC:

public class UserModel
{
    public string Login { get; set; }

    [DisplayName("Display Name")]
    public string DisplayName { get; set; }

    public static explicit operator UserModel(string userLogin)
    {
        IKernel IoC; // Where do I get this from?
        var ActiveDirRepo = IoC.Get<IActiveDirectoryRepository>();

        var User = ActiveDirRepo.FindById<ActiveDirectoryUser>(userLogin.ToUpper());

        return new UserModel()
        {
            Login = userLogin,
            DisplayName = User == null ? userLogin.ToUpper() : User.Name
        };
    }
}

它有一個從stringUserModel的顯式轉換運算符。 以前我只是new了一個ActiveDirectoryRepository並使用它,但我想開始使用IoC / DI。

我現在遇到的問題是,如何引用我的IoC容器( IKernel )?

我不能從外部將它注入UserModel ,因為操作員正在創建它。

您可以使用服務定位器模式表單Microsoft.Practices.ServiceLocation如果ninject不提供實現,我將被取消。 如果不是,那就直接實施了。

無論您是否可以使用此代碼執行所需操作,我強烈建議您不要像以前那樣實現顯式轉換運算符。 這是一個不好的做法。

IoC沒有什么神奇之處。 有時您仍然需要一個起點,您可以從中獲取應用程序的IoC容器,如下所示:

var ioc = Application.Instance.Container.Get<IActiveDirectoryRepository>();

您不需要從任何地方訪問IoC容器,因為通過容器創建的對象已經注入了它們的依賴項,但至少有一些根對象需要訪問容器。

這種轉換假設很簡單,這並不需要外部依賴。 如果你需要注入某種依賴,那么忘記轉換,沒有解決方案。

很簡單,將IKernel傳遞給構建方法:

public static UserModel Build(string userLogin, IKernel IoC)
{
    var ActiveDirRepo = IoC.Get<IActiveDirectoryRepository>();

    var User = ActiveDirRepo.FindById<ActiveDirectoryUser>(userLogin.ToUpper());

    return new UserModel()
    {
        Login = userLogin,
        DisplayName = User == null ? userLogin.ToUpper() : User.Name
    };
}

然后你可以問自己這個方法是否屬於IKernel接口是否有意義:

interface IKernel
{
    UserModel Build(string userLogin);
}

在意識形態上,您的IoC容器應該只存在於應用程序的復合根中。 考慮到這一點,這是一個計算你的類依賴關系並通過構造函數注入它們的問題(如果你不能使用構造函數DI,那么許多IoC容器提供了替代的注入方法)。

在這里,您需要訪問IActiveDirectoryRepository才能創建UserModel。 但是,您的創建方法, explicit operator UserModel是一個無法訪問實例變量的靜態方法。 不幸的是,這限制了你使用依賴注入來利用IoC的能力,所以這里有一些想法:

  • 直截了當 :使用服務定位器模式。 您使用服務定位器來獲取IActiveDirectoryRepository的實例。 這將直接適應您當前的實現(將內核行交換到服務定位器)。 但是,這種模式存在缺陷; 最值得注意的是,您正在內化IActiveDirectoryRepository源,這會使單元測試效率降低。

  • 傳統 :將UserModel創建者放入一個工廠,通過它的構造函數接受IActiveDirectoryRepository 然后,工廠創建的任何UserModel使用提供的IActiveDirectoryRepository

     public sealed class UserFactory { private readonly IActiveDirecotryRepository repository; public UserFactory(IActiveDirectoryRepository repository) { this.repository = repository; } public UserModel CreateNewUser(string userLogin) { var User = repository.FindById<ActiveDirectoryUser>(userLogin.ToUpper()); return new UserModel() { Login = userLogin, DisplayName = User == null ? userLogin.ToUpper() : User.Name } } } 
  • Fancy :在IActiveDirectoryRepository創建一個閉包, IActiveDirectoryRepository創建者作為第一類函數傳遞。

     static Func<string, UserModel> CreateFactory(IActiveDirectoryRepository repository) { return (userLogin) => { var User = repository.FindById<ActiveDirectoryUser>(userLogin.ToUpper()); return new UserModel() { Login = userLogin, DisplayName = User == null ? userLogin.ToUpper() : User.Name } } } 

暫無
暫無

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

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