繁体   English   中英

具有相同接口的两个实例的Castle Windsor注入控制器

[英]Castle Windsor injecting controller with two instances of same interface

我有这样的控制器

public class MyController : Controller
{
    private IEntityRepository accountsRepo;
    private IEntityRepository dataRepo;

    public MyController(IEntityRepository accs, IEntityRepository data)
    {
        accountsRepo = accs;
        dataRepo = data;
    }
.....
}

我以这种方式安装了容器:

public class RepositoriesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IEntityRepository>()
                .ImplementedBy<AccountsRepository>()
                .Named("accs")
                .LifestyleTransient(),
            Component.For<IEntityRepository>()
                .ImplementedBy<DataRepository>()
                .Named("data")
                .LifestyleTransient());

    }
}

我还设置了以下设施:

public class PersistenceFacility : AbstractFacility
{
    protected override void Init()
    {
        Kernel.Register(
            Component.For<DbContext>()
                .ImplementedBy<AccountsContext>()
                .LifestylePerWebRequest(),
            Component.For<DbContext>()
                .ImplementedBy<DataContext>()
                .LifestylePerWebRequest());
    }
}

}

...并安装:

public class PersistenceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<PersistenceFacility>();
    }
}

因此,当我使用控制器时,两个参数都将与AccountsRepository实例一起注入(该实例首先被注册)。 当然,我想分别将“数据”作为DataRepository。 请给我解释处理这种注射的正确方法。

编辑

正如@roman所建议的,我已经实现了通用存储库:

public interface IRepository : IDisposable
{
    void SaveChanges();

    void ExecuteProcedure(String procedureCommand, params SqlParameter[] sqlParams);
}

public interface IEntityRepository<T> : IRepository
{
    T Context { get; set; }
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
}

public class AccountsRepository : IEntityRepository<AccountsContext>
{
    public AccountsContext Context { get; set; }

    public AccountsRepository(AccountsContext c)
    {
        Context = c;
    }

    public DbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return Context.Set<TEntity>();
    }

    public virtual void ExecuteProcedure(String procedureCommand, params SqlParameter[] sqlParams)
    {
        Context.Database.ExecuteSqlCommand(procedureCommand, sqlParams);
    }

    public virtual void SaveChanges()
    {
        Context.SaveChanges();
    }

    public void Dispose()
    {
        if (Context != null)
            Context.Dispose();
    }
}

DataRepository看起来是一样的,在某种程度上,我将决定只拥有一个具体的类EntityRepository,但它与我收到的异常无关。 因此,在外观界面更改后,我的控制者变为:

public class HomeController : Controller
{
    private IEntityRepository<AccountsContext> accountsRepo;
    private IEntityRepository<DataContext> dataRepo;

    public HomeController(IEntityRepository<AccountsContext> accs, IEntityRepository<DataContext> data)
    {
        accountsRepo = accs;
        dataRepo = data;
    }
    ....
}

我也更改了安装程序代码:

        container.Register(
            Component.For<IEntityRepository<AccountsContext>>()
                .ImplementedBy<AccountsRepository>()
                .LifestyleTransient(),
            Component.For<IEntityRepository<DataContext>>()
                .ImplementedBy<DataRepository>()
                .LifestyleTransient());

现在在控制器解决过程中

        return (IController) kernel.Resolve(controllerType);

我赶上

无法创建组件“ MyMVCProj.DAL.AccountsRepository”,因为它具有要满足的依赖关系。

'MyMVCProj.DAL.AccountsRepository' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.

Castle.MicroKernel.Handlers.HandlerException: Can't create component     'MyMVCProj.DAL.AccountsRepository' as it has dependencies to be satisfied.

'MyMVCProj.DAL.AccountsRepository' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.

但是我已经在设施逻辑中安装了AccountsContext。

编辑++根据@Roman的建议,我以这种方式调整了我的设施:

public class PersistenceFacility : AbstractFacility
{
    protected override void Init()
    {
        Kernel.Register(
            Component.For<DbContext>()
                .ImplementedBy<AccountsContext>()
                .Named("accctx")
                .LifestylePerWebRequest(),
            Component.For<DbContext>()
                .ImplementedBy<DataContext>()
                .Named("datactx")
                .LifestylePerWebRequest());
    }
}

以及仓库安装程序:

public class RepositoriesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IEntityRepository<AccountsContext>>()
                .ImplementedBy<AccountsRepository>()
                .Named("accs‌​")
                .LifestyleTransient()
                .DependsOn(Dependency.OnComponent(typeof (DbContext), "accctx")),
            Component.For<IEntityRepository<DataContext>>()
                .ImplementedBy<DataRepository>()
                .Named("data")
                .LifestyleTransient()
                .DependsOn(Dependency.OnComponent(typeof (DbContext), "datactx")));
    }
}

这是我现在得到的例外:

Can't create component 'accs‌​' as it has dependencies to be satisfied.
'accs‌​' is waiting for the following dependencies:
- Service 'MyMVCProj.DAL.AccountsContext' which was not registered.

但是,为了解决这种残酷的行为,我以有效的解决方案结束了代码,只是安装了DBContext的具体实现:

public class PersistenceFacility : AbstractFacility
{
    protected override void Init()
    {
        Kernel.Register(
            Component.For<AccountsContext>().LifestylePerWebRequest(),
            Component.For<DataContext>().LifestylePerWebRequest());
    }
}

现在内核的组件是:

    AccountsContext PerWebRequest   
    AccountsRepository / IEntityRepository<AccountsContext> Transient
    DataContext PerWebRequest   
    DataRepository / IEntityRepository<DataContext> Transient

在他们之前:

    AccountsContext / DbContext PerWebRequest   
    AccountsRepository / IEntityRepository<AccountsContext> Transient
    DataContext / DbContext PerWebRequest   
    DataRepository / IEntityRepository<DataContext> Transient

因此,新问题是:

我是否习惯了所有工作? 为什么会出现这种行为-已经有AccountContext很少提及它的依赖关系。

您期望有相同接口的两个实例,但您需要对它们采取不同的行为(通过将它们注入两个不同的参数),这一事实(在我看来)意味着它们不应该是同一接口,因为它们具有不同的作用,或责任。 如果IEntityRepository是一个通用类,那么对我来说更有意义,那么您将在MyController中要求两种不同的通用接口类型:

public class MyController(IEntityRepository<Account> acc, IEntityRepository<Data> data)

不过,如果您仍然想做这种事情,我建议您使用CollectionResolver,它将允许MyController类获取IEnumerable。 这样,您将获得两个实例,但是将取决于您的需求来选择合适的实例,我会再次强调,我认为这是错误的方法。

要使用CollectionResolver,您需要像这样在Windsor容器中注册它:

var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

然后,MyController将如下所示:

 public class MyController(IEnumerable<IEntityRepository> repositories)
 {
    accountsRepo = repositories.Where(...);
    dataRepo = repositories.Where(...);
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM