我最近一直在使用依赖注入(Unity)来实现我的域层与任何基础架构问题之间的低耦合。
我最终在我的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>>()
)
);
有没有更好的方法来组织这个?
我似乎无法在网上找到任何示例/文章/指示。
答案 0 :(得分:1)
通常,您要做的是为应用程序的每个逻辑组件创建“模块”,并在模块的Initialize方法中设置映射。在引导程序中,您可以设置要加载的模块。有多种方法可以做到这一点。您可以在代码,XML或使用DLL Discovery中明确地执行此操作。
通常,您不会在引导程序中设置映射。您只需确定要在引导程序中加载的内容,并允许模块设置所需的映射。
如果您的问题是如何阻止在代码中的任何地方完成映射(即没有container.RegisterInstance&lt; ...&gt;),据我所知,这是不可能的。有关如何映射接口的信息必须来自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()更改为仅添加您要使用的模块。