如何根据Castle Windsor中的泛型类型参数解析服务?

时间:2013-02-20 18:32:39

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

我有这样的安装程序:

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的包装器,但它接受一个类型参数来指示它需要连接的数据库。我的想法是我有几个DbContexts,因为我需要连接到多个数据库,我希望windsor根据传递给存储库的类型参数来解析相应的DBcontext。

存储库类型参数受限于以下内容(GlobalObject和GlobalContext引用与1个此类数据库关联的类型):

public interface IGlobalObject : IObject
    {}

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

然而,温莎无法解决上下文,我无法解决为什么?它已注册并在容器中,但无法解决。

修改

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());

2 个答案:

答案 0 :(得分:0)

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

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

在这里你要说 - 当有人要求Context注入一个GlobalContext&lt;&gt; - 问题是windsor如何知道GlobalContext的泛型参数是什么。

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

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

答案 1 :(得分:0)

这不是你问题的直接答案。但我觉得这种做法可能是错的。

考虑到您的存储库是由通用基础Repository<>实现的,我无法看到将通用类型与正确的上下文相关联的简洁方法。我认为您可能需要切换到“风味”存储库,并在其中注入明确的上下文和/或在注册上下文时更加冗长。