1

Я недавно использовал инъекцию зависимостей (Unity) для достижения низкой связи между уровнями моего домена и любыми инфраструктурными проблемами.DI Организация контейнерного кода

Я закончил с много кода контейнера Unity в моем загрузчике MVC.

Небольшой фрагмент кода:

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 .., которое устраняет необходимость индивидуально привязывать шаблонный код, подобный этому. Возможно, для Единства есть что-то подобное? –

+0

Может быть (я тоже не человек Единства), но я не могу найти ничего. – davenewza

ответ

1

Как правило, вы должны создать «Модули» для каждого логического компонента вашего приложения и установить сопоставления в методе Initialize модуля. В вашем загрузчике вы устанавливаете, какие модули вы хотите загрузить. Существует несколько способов сделать это. Вы можете явно сделать это в коде, в XML или с помощью DLL Discovery.

Обычно вы не устанавливаете сопоставления в загрузчике. Вы просто решаете, что вы хотите загрузить в загрузчике, и разрешите модулю устанавливать необходимые ему сопоставления.

Если у вас есть вопрос, как вы вообще не можете делать сопоставления (т. Е. Нет контейнера.RegisterInstance < ...>) в любом месте кода, это невозможно, насколько я знаю. Информация о том, как отображать интерфейсы, должна поступать из SOMEWHERE.

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

EDIT:

Создание модуля для каждого логического раздела. Я сделаю одно для FirstContext и AnotherContext. Я обычно помещаю модуль на DLL, но нет ничего, что помешало бы вам создать более 1 модуля на 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

Смежные вопросы