1

我最近一直在使用依赖注入(Unity)来实现我的领域层和任何基础设施问题之间的低耦合。

我已经结束了很多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>>()
    )
);

有没有更好的方法来组织这个?

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

4

1 回答 1

1

通常,您要做的是为应用程序的每个逻辑组件创建“模块”,并在模块的 Initialize 方法中设置映射。在您的引导程序中,您可以设置要加载的模块。有多种方法可以做到这一点。您可以在代码中、在 XML 中或通过使用 DLL Discovery 显式地执行此操作。

通常您不会在引导程序中设置映射。您只需决定要在引导程序中加载什么并允许模块设置它需要的映射。

如果您的问题是如何避免在代码中的任何地方进行映射(即没有 container.RegisterInstance<...>),据我所知这是不可能的。有关如何映射接口的信息必须来自某个地方。

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

编辑:

为每个逻辑部分创建一个模块。我将为 FirstContext 和 AnotherContext 做一个。我通常为每个 DLL 放置一个模块,但没有什么能阻止您为每个 DLL 创建多个模块。由您决定如何组织它。

第一个上下文模块:

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

另一个上下文模块:

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() 以仅添加您要使用的模块。

于 2014-02-13T18:05:47.613 回答