Castle Windsor:开放式泛型类型的条件注册

3

我有以下内容:

class Repository<T> : IRepository<T>
interface ISuperRepository<T> : IRepository<T>
class SuperRepository<T> : ISuperRepository<T>
interface ISuperType

我希望在Castle Windsor DI中对IRepository进行条件注册,如果T是ISuperType,则提供ISuperRepository。否则,提供IRepository。
例如,如果A: ISuperType,则我希望Resolve>提供SuperRepository,并且Resolve>提供Repository
如何实现这一点?

每一层间接性(也称为条件)都可以通过另一层抽象 - FactoryProvider来解决。 - Ognyan Dimitrov
2个回答

2

Castle Windsor 不支持这样的功能,但是你可以通过一个简单的辅助方法来实现:

public static void RegisterAccordingToISuperType<T>(this IWindsorContainer container)
{
    if (typeof (T).GetInterfaces().Contains(typeof (ISuperType)))
        container.Register(Component.For<IRepository<T>>()
                                    .ImplementedBy<SuperRepository<T>>());
    else
        container.Register(Component.For<IRepository<T>>()
                                    .ImplementedBy<Repository<T>>());
}

然后是注册:
container.RegisterAccordingToISuperType<SuperType>();
container.RegisterAccordingToISuperType<int>();

解决方案将会:

var super = container.Resolve<IRepository<SuperType>>();
var intRepo = container.Resolve<IRepository<int>>();

另一个选项是在 Component.For 中添加额外参数。然后获取所有继承自该类型的类型(例如)并注册它们。
private static void Register(...)
{
    foreach (var type in GetInheriteTypes())
    {          
        container.Register(Component.For(typeof(IRepository<>),type)
                                    .ImplementedBy(typeof(SuperRepository<>)));
    }
    container.Register(Component.For(typeof(IRepository<>))
                                .ImplementedBy(typeof(Repository<>)));
}

private static IEnumerable<Type> GetInheriteTypes()
{
    var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                    from assemblyType in domainAssembly.GetTypes()
                    where assemblyType.GetInterfaces().Contains(typeof(ISuperType))
                    select assemblyType).ToArray();
    return listOfBs;
}

谢谢回复 - 我有很多实现ISuperType的类,所以我喜欢第二种方法,但它似乎不起作用 - 解析的类型总是SuperRepository<T>而不是Repository<T>。 - Rita
@Rita 你的 Resolve 看起来怎么样?如果 Resolve 看起来像我的例子,它应该可以工作(在我的电脑上它可以工作)。 - Old Fox
@Rita 还有一件事,要确认在foreach之前你没有注册任何内容。如果这样做了,你必须使用Default()扩展方法。 - Old Fox
我无法让它工作。Component.For(typeof(IRepository<>),type)完全忽略了类型。最终我使用MakeGenericType进行注册。如果您能告诉我问题在哪里,我将不胜感激。无论如何,这是代码,对我有效:foreach(var type in types) { container.Register(Component.For(typeof(IRepository<>).MakeGenericType(type)) .ImplementedBy(typeof(SuperRepository<>).MakeGenericType(type))); } - Rita
我忘了提到,我还需要注册 Component.For(typeof(ISuperRepository<>)).ImplementedBy(typeof(SuperRepository<>))。 - Rita

-1

您可以使用“where T:typename”语法限制泛型可用于哪些类型,其中“typename”是指指定类型'T'必须继承(或实现)的类型。在您的情况下,“where T:ISuperType”将匹配特定类型,而没有限制的版本将匹配所有其他类型。

参考 https://msdn.microsoft.com/en-us/library/bb384067.aspx

如果无法在编译时完成,则始终可以在运行时完成(例如使用'is')。


1
这不是我遇到的问题。我正在寻找在Castle Windsor DI中进行条件注册的方法。 - Rita
如果“注册”意味着“运行代码”(虽然我对此有一些了解,但从未深入研究过),那么有什么阻止测试T是否为ISuperType类型?在这里,我假设有一个小型的“工厂”来创建这些存储库对象,以便可以选择正确的存储库对象。 - tamlin
2
@tamlin 你可能想要了解依赖注入的概念以及特别是Castle Windsor - GSerg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接