为什么此简单注入器注册会导致集合为空?



我有一个通用接口,它有许多实现,可能在不同的程序集中。我通过 NuGet 在我的项目中安装了简单注入器 4.3.0,并希望将实现器注册为集合。我的配置已由简单注入器验证,没有发生任何事件,但在调用 GetAllInstances 时容器返回一个空集合。

类似于我的代码的MCVE:

using SimpleInjector;
using System;
using System.Linq;
namespace SIMultiInterfaceTest
{
public interface IFoo<T> { }
public class Bar<T> : IFoo<T> { }
public class Baz<T> : IFoo<T> { }
class Program
{
static void Main(string[] args)
{
var container = new Container();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
container.Collection.Register(typeof(IFoo<>), assemblies);
container.Verify();
Console.WriteLine($"{container.GetAllInstances<IFoo<int>>().Count()} in collection");
Console.ReadLine();
}
}
}

作为参考,我正在尝试实现 SI 文档本节末尾提到的注册方案(ctrl+f:"例如,假设您有一个客户验证器类型和一个 GoldCustomerValidator 类型的场景"(。

为什么此简单注入器注册会导致集合为空?

我的直觉是,这可能与Bar<T>有关,Baz<T>是开放泛型类型 - 该示例仅显示以这种方式注册的封闭类型。但是,我不相信,因为这似乎与导致这一完全有效行的设计选择相反,也来自文档中的同一页面:

container.Register(typeof(IValidate<>), typeof(NullValidator<>));

此行为在 XML 注释中对要调用的Collection.Register(Type, Assembly[])重载进行了说明:

注册在给定assemblies集中定义的所有具体的非泛型类型(公共和内部类型(,这些类型以默认生活方式实现给定serviceType,并将它们注册为serviceType集合。[强调我的]

但是,您的类型是泛型的。泛型类型未注册,因为它们通常需要特别小心。

若要注册这些泛型类型,有两个选项。

可以使用Collection.Append将这些类型追加或追加到集合:

// Bar<T> is prepended
container.Collection.Append(typeof(IFoo<>), typeof(Bar<>));
// All non-generic registrations next
container.Collection.Register(typeof(IFoo<>), assemblies);
// Baz is appended. It will be the last element of the collection
container.Collection.Append(typeof(IFoo<>), typeof(Baz<>));

第二个选项是使用GetTypesToRegister获取所有类型,包括泛型类型:

var types = container.GetTypesToRegister(
typeof(IFoo<>),
assemblies,
new TypesToRegisterOptions { IncludeGenericTypeDefinitions = true });
container.Collection.Register(typeof(IFoo<>), types);

在这里,我们调用GetTypesToRegister,同时提供一个指示它也应该返回泛型类型的TypesToRegisterOptions。此类型列表提供给Collection.Register(Type, Type[])重载。

但是,请注意,在第二个选项中,类型的注册顺序是不确定的,并且每次重新编译甚至重新启动应用程序时都可能会更改。如果此行为不适合,则必须先订购类型集,然后再将其提供给Collection.Register

最新更新