【问题标题】:How can I resolve a service based upon generic type argument in Castle Windsor?如何根据 Castle Windsor 中的泛型类型参数解析服务?
【发布时间】:2013-02-20 18:32:38
【问题描述】:

我有一个这样的安装程序:

public void Install(IWindsorContainer container, IConfigurationStore store) {

        //Services
        container.Register(
            Classes.FromAssemblyNamed(ASSEMBLY_NAME)
                .BasedOn<IService>()
                .WithServiceFirstInterface()
                .LifestyleTransient());

        //Repository
        container.Register(
            Component.For(typeof(IRepository<>))
                .ImplementedBy(typeof(Repository<>))
                .LifestyleTransient());

        //Contexts
        container.Register(
            Component.For(typeof(Context<IGlobalObject>))
                .ImplementedBy(typeof(GlobalContext<>)).LifestyleTransient());

    }

存储库是一个开放的泛型,它注入了一个 Context 构造函数,它是一个围绕 EF DbContext 的包装器,但需要一个类型参数来指示它需要连接到的数据库。我的想法是我有几个 DbContext,因为我需要连接到多个数据库,并且我希望 Windsor 根据传递给存储库的类型参数解析适当的 DBcontext。

repositories 类型参数受限于以下内容(GlobalObject 和 GlobalContext 指的是与 1 个此类数据库关联的类型):

public interface IGlobalObject : IObject
    {}

    public interface IObject
    {
        int Key { get; set; }
    }

但是,Windsor 无法解析上下文,我不知道为什么?它已注册并在容器中,但无法解析。

编辑:

GlobalContext 的代码:

public class GlobalContext<T> : Context<T>
    where T : IGlobalObject
{
    private const string GLOBAL_CSTR = "Global";

    public GlobalContext() : base(ConfigurationManager.ConnectionStrings[GLOBAL_CSTR].ConnectionString) {}

    public DbSet<Company> Companies { get; set; }
    public DbSet<ConnectionString> ConnectionStrings { get; set; }
    public DbSet<Server> Servers { get; set; }
}

上下文:

//Wrapper around dbcontext which enforces type
    public abstract class Context<T> : DbContext where T : IObject
    {
        protected Context() {}
        protected Context(string connectionString)  : base(connectionString){}
    }

编辑 2:

如果我为它工作的每个场景指定具体类型,那么显然与界面上的匹配有关。

//Contexts
        container.Register(
            Component.For(typeof(Context<Server>))
                .ImplementedBy(typeof(GlobalContext<Server>)).LifestyleTransient());

【问题讨论】:

    标签: entity-framework generics inversion-of-control castle-windsor repository-pattern


    【解决方案1】:

    这对我来说似乎是个问题:

    //Contexts
    container.Register(
        Component.For(typeof(Context<IGlobalObject>))
            .ImplementedBy(typeof(GlobalContext<>)).LifestyleTransient());
    

    你在这里说 - 当有人要求 Context 注入 GlobalContext - 问题是 Windsor 如何知道 GlobalContext 的通用参数是什么。

    如果没有看到您的 GlobalContext 对象,很难看到它,但它应该是:

    container.Register(
        Component.For(typeof(Context<>))
            .ImplementedBy(typeof(GlobalContext<>)).LifestyleTransient());
    

    【讨论】:

    • 这完全有道理,但遗憾的是没有奏效。我已经添加了 Context 和 GlobalContext 的代码。干杯
    • 好的 - 我想我现在理解得更好了,我做了一个小修改 - 删除了通用参数。
    【解决方案2】:

    这并不是您问题的直接答案。但我觉得这种方法可能是错误的。

    考虑到您的存储库是由通用基础Repository&lt;&gt; 实现的,我看不到将通用类型与正确上下文相关联的干净方法。我认为您可能需要切换到具有显式上下文注入的“风味”存储库和/或在注册上下文的方式上更加冗长。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多