我正在使用自定义 JsonConverter 和 JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects
在反序列化期间创建所需的实例。这些实例是通过解析来自 Autofac IOC 容器的类型来创建的。一切正常,除了...
我有几个“核心对象”,它们从服务的构造函数中请求一个唯一的 Id(正确地注入(inject)到构造函数中)。反序列化时不应该发生这种情况,因为它相当昂贵,并且一旦创建实例,Id 就会从 Json 文件中填充。
目前,当从自定义 JsonConverter 中解析时,我使用的是 _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null));
然后 - 在调用的构造函数中 - 检查 null 并采取相应行动。
有些人显然认为使用 IOC 时使用多个构造函数比代码味道更糟糕(这让我想知道为什么 Autofac 提供了与该主题相关的多个功能),但在反序列化的上下文中,我认为它非常有意义。
据我所知,Autofac 具有决定在注册 期间使用哪个构造函数的机制,但在解析 时则不然。我的首选解决方案是将自定义属性添加到构造函数(例如 [CtorForDeserializing]
)并使用它来决定。这可能吗?
最佳答案
Autofac 有几个扩展点用于基于反射的激活,但还没有很好的文档记录,它们可能对您有所帮助:IConstructorFinder
和 IConstructorSelector
。
IConstructorFinder
用于定位一个类型的所有可用构造函数。核心示例是 DefaultConstructorFinder
它只定位公共(public)构造函数。例如,如果您想隐藏具有特定属性的构造函数或开始查找内部/私有(private)构造函数,您可以创建一个自定义查找器。这实际上只发生一次,因此您不必在此处做出运行时选择。
IConstructorSelector
用于在解析时选择应该使用哪个构造函数来实例化对象。核心 Autofac 中有几个,但主要示例是 MostParametersConstructorSelector
它选择当时具有最多可用匹配参数的构造函数。构造函数由 IConstructorFinder
找到,然后将那组构造函数呈现给 IConstructorSelector
以供选择。这是您可以做出更多运行时选择的地方,因为它会在每次解析对象时发生。
有一些扩展方法可以帮助您将查找器/选择器添加到注册中:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
您不必自定义这两件事,您可以根据需要只做其中之一。我只是向您展示扩展。
关于c# - 如何确定 Autofac 在解析时使用哪个构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50533374/