1

我最近一直在使用依賴注入(Unity)來實現我的域層和任何基礎結構關注點之間的低耦合。DI容器代碼組織

我在我的MVC引導程序中結束了與很多的Unity容器代碼。

一個小片段:

container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>("FirstContext", new PerResolveLifetimeManager(), new InjectionConstructor(new FirstContext())); 
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>("AnotherContext", new PerResolveLifetimeManager(), new InjectionConstructor(new AnotherContext())); 

// User Aggregate 
container.RegisterType<IEntityMapper<User, UserTable>, UserMapper>(); 
container.RegisterType<IUserRepository, UserRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("FirstContext"), 
     new ResolvedParameter<IEntityMapper<User, UserTable>>() 
    ) 
); 

// Token Aggregate 
container.RegisterType<IEntityMapper<Token, TokenTable>, TokenMapper>(); 
container.RegisterType<ITokenRepository, TokenRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("FirstContext"), 
     new ResolvedParameter<IEntityMapper<Token, TokenTable>>() 
    ) 
); 

// Payment Aggregate 
container.RegisterType<IReadOnlyEntityMapper<Payment, PaymentTable>, PaymentFactory>(); 
container.RegisterType<IPaymentRepository, PaymentRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("FirstContext"), 
     new ResolvedParameter<IReadOnlyEntityMapper<Payment, PaymentTable>>() 
    ) 
); 

// Customer Aggregate 
container.RegisterType<IReadOnlyEntityMapper<Customer, CustomerTable>, CustomerMapper>(); 
container.RegisterType<ICustomerRepository, CustomerRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
     new ResolvedParameter<IReadOnlyEntityMapper<Customer, CustomerTable>>() 
    ) 
); 

// Country Aggregate 
container.RegisterType<IReadOnlyEntityMapper<Country, CountryTable>, CountryMapper>(); 
container.RegisterType<ICountryRepository, CountryRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
     new ResolvedParameter<IReadOnlyEntityMapper<Country, CountryTable>>() 
    ) 
); 

// Province Aggregate 
container.RegisterType<IReadOnlyEntityMapper<Province, ProvinceTable>, ProvinceMapper>(); 
container.RegisterType<IProvinceRepository, ProvinceRepository>(
    new InjectionConstructor(
     new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
     new ResolvedParameter<IReadOnlyEntityMapper<Province, ProvinceTable>>() 
    ) 
); 

有沒有更好的方式來組織呢?

我似乎無法在網上找到任何示例/文章/方向。

+1

我不是一個團結人..但肯定有一種方法來模塊化這些?我覺得有時候Ninject會被寵壞......你可以創建NinjectModule來註冊類型。還有Ninject Conventions Extension ..這樣就不需要像這樣單獨綁定樣板代碼。也許有這樣的Unity的東西? –

+0

可能有(我不是一個團結人)但我似乎無法找到任何東西。 – davenewza

回答

1

通常,您要做的是爲應用程序的每個邏輯組件創建「模塊」,並在模塊的Initialize方法中設置映射。在您的引導程序中,您可以設置要加載的模塊。有多種方法可以做到這一點。您可以在代碼中,使用XML或使用DLL發現來顯式執行此操作。

通常情況下,您不會在引導程序中設置映射。您只需決定要在引導程序中加載的內容,並允許該模塊設置它所需的映射。

如果你的問題是你如何防止必須在代碼中的任何地方完成映射(即沒有container.RegisterInstance < ...>),那麼據我所知,這是不可能的。有關如何映射界面的信息必須來自SOMEWHERE。

http://msdn.microsoft.com/en-us/library/gg405479(v=pandp.40).aspx

編輯:

創建每個邏輯部分的模塊。我會爲FirstContext和AnotherContext做一個。我通常爲每個DLL放置一個模塊,但沒有任何東西阻止您爲每個DLL創建多個模塊。這取決於你如何組織它。

FirstContextModule:

public class FirstContextModule : IModule 
{ 
    private readonly IUnityContainer container; 

    public FirstContextModule(IUnityContainer unityContainer) 
    { 
     this.container = unityContainer; 
    } 

    public void Initialize() 
    { 
     this.SetupContainer(); 
     this.SetupRegions(); 
    } 

    private void SetupContainer() 
    { 
     container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>("FirstContext", new PerResolveLifetimeManager(), new InjectionConstructor(new FirstContext())); 

     // User Aggregate 
     container.RegisterType<IEntityMapper<User, UserTable>, UserMapper>(); 
     container.RegisterType<IUserRepository, UserRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("FirstContext"), 
       new ResolvedParameter<IEntityMapper<User, UserTable>>())); 

     // Token Aggregate 
     container.RegisterType<IEntityMapper<Token, TokenTable>, TokenMapper>(); 
     container.RegisterType<ITokenRepository, TokenRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("FirstContext"), 
       new ResolvedParameter<IEntityMapper<Token, TokenTable>>())); 

     // Payment Aggregate 
     container.RegisterType<IReadOnlyEntityMapper<Payment, PaymentTable>, PaymentFactory>(); 
     container.RegisterType<IPaymentRepository, PaymentRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("FirstContext"), 
       new ResolvedParameter<IReadOnlyEntityMapper<Payment, PaymentTable>>())); 
    } 

    private void SetupRegions() 
    { 
     // Register the views 
    } 
} 

AnotherContextModule:

public class AnotherContextModule : IModule 
{ 
    private readonly IUnityContainer container; 

    public AnotherContextModule(IUnityContainer unityContainer) 
    { 
     this.container = unityContainer; 
    } 

    public void Initialize() 
    { 
     this.SetupContainer(); 
     this.SetupRegions(); 
    } 

    private void SetupContainer() 
    { 
     container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>("AnotherContext", new PerResolveLifetimeManager(), new InjectionConstructor(new AnotherContext())); 

     // Customer Aggregate 
     container.RegisterType<IReadOnlyEntityMapper<Customer, CustomerTable>, CustomerMapper>(); 
     container.RegisterType<ICustomerRepository, CustomerRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
       new ResolvedParameter<IReadOnlyEntityMapper<Customer, CustomerTable>>())); 

     // Country Aggregate 
     container.RegisterType<IReadOnlyEntityMapper<Country, CountryTable>, CountryMapper>(); 
     container.RegisterType<ICountryRepository, CountryRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
       new ResolvedParameter<IReadOnlyEntityMapper<Country, CountryTable>>())); 

     // Province Aggregate 
     container.RegisterType<IReadOnlyEntityMapper<Province, ProvinceTable>, ProvinceMapper>(); 
     container.RegisterType<IProvinceRepository, ProvinceRepository>(
      new InjectionConstructor(
       new ResolvedParameter<IUnitOfWork>("AnotherContext"), 
       new ResolvedParameter<IReadOnlyEntityMapper<Province, ProvinceTable>>())); 
    } 

    private void SetupRegions() 
    { 
     // Register the views 
    } 
} 

引導程序:

public class Bootstrapper : UnityBootstrapper 
{ 
    protected override void ConfigureModuleCatalog() 
    { 
     base.ConfigureModuleCatalog(); 

     ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog; 
     moduleCatalog.AddModule(typeof(FirstContextModule)); 
     moduleCatalog.AddModule(typeof(AnotherContextModule)); 
    } 

    protected override DependencyObject CreateShell() 
    { 
     return this.Container.Resolve<Shell>(); 
    } 

    protected override void InitializeShell() 
    { 
     base.InitializeShell(); 

     Application.Current.MainWindow = (Window)this.Shell; 
     Application.Current.MainWindow.Show(); 
    } 
} 

現在,它的分成模塊,讓我們假設你想3個不同版本的應用程序:
1只使用FirstContext 1只使用AnotherContext 1同時使用FirstContext和AnotherContext

所有你需要做的更改ConfigureModuleCatalog()以僅添加要使用的模塊。

+0

你會在哪裏定義這些模塊?任何代碼都會很棒。謝謝 – davenewza

+0

@davenewza檢查一些代碼示例的編輯。 – TTat