在 Autofac 中,RegisterAssemblyOpenGenericTypes 和 RegisterAssemblyTypes with AsClosedTypesOf 有什么区别?
In Autofac, what is the difference between RegisterAssemblyOpenGenericTypes and RegisterAssemblyTypes with AsClosedTypesOf?
我有一个由多个具体实现的通用接口 class。例如:
public interface IMyInterface<T> {}
internal class Impl1 : IMyInterface<int> {}
internal class Impl2 : IMyInterface<float> {}
我想自动注册 IMyInterface<T>
的所有实现,以便我可以解析类型 T
支持的特定实现(在本例中,int
或 float
).例如:
class TheConsumer
{
// `impl` should resolve to `Impl1`
public TheConsumer(IMyInterface<int> impl) {}
}
根据我从 this github issue and the documentation 收集到的信息,似乎有两种机制可以做到这一点:
var builder = new ContainerBuilder();
// Mechanism 1
builder.RegisterAssemblyOpenGenericTypes(typeof(Startup).Assembly)
.AssignableTo(typeof(IMyInterface<>))
.AsImplementedInterfaces();
// Mechanism 2
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsClosedTypesOf(typeof(IMyInterface<>))
.AsImplementedInterfaces();
我只成功测试了上面显示的第二种机制。第一个我推测是一样的;但它可能不是。总的来说,我真的很困惑 Autofac 是如何处理“泛型”的。文档也没有提及 RegisterAssemblyOpenGenericTypes
,这无济于事。所以这是我的问题:
- 以上两个版本在功能上有什么区别?
- 在什么情况下你会选择其中之一?
- 什么是“开放”和“封闭”泛型(来自 Autofac 文档的术语)?
What is an "open" and "closed" generic (terminology from the Autofac documentation)?
开放泛型具有未定义的类型参数(例如 List<T>
)。然而,封闭的泛型具有定义的类型参数(例如 List<int>
)。
- What is the functional difference between the two versions above?
目前,您的两个实现都是 IMyInterface<T>
:
的“封闭式”通用实现
internal class Impl1 : IMyInterface<int> { }
internal class Impl2 : IMyInterface<float> { }
当您将 RegisterAssemblyOpenGenericTypes
(“机制 1”)与这些一起使用时,您会得到一个异常,即在解析 TheConsumer
时 IMyInterface<int>
未知。当您将 RegisterAssemblyTypes
与这些封闭的通用实现一起使用时,Impl1
在解析 TheConsumer
.
时会按预期传递
RegisterAssemblyOpenGenericTypes
的用法可以通过稍微扩展您的示例来说明。如果您添加 IMyInterface<T>
的另一个实现,例如:
internal class Impl3<T> : IMyInterface<T> { }
您知道 IMyInterface<T>
有一个“开放”的通用实现。因此,当您返回 RegisterAssemblyOpenGenericTypes
(“机制 1”)并尝试解析 TheConsumer
时,它起作用了,并且传入了 Impl3<int>
。
In what case would you choose one or the other?
将 RegisterAssemblyTypes
与您当前拥有的“封闭”泛型类型一起使用,IMyInterface<T>
的用户将只能解析使用该类型专门实现的接口(例如 IMyInterface<int>
由 Impl1
实现)。当您只想要在 IMyInterface<T>
.
中使用的一组特定类型参数时,这可能是理想的选择
当您实际上并不关心 IMyInterface<T>
中使用的类型参数是什么时,使用 RegisterAssemblyOpenGenericTypes
会很有用。这本质上只是允许更灵活地使用 IMyInterface<T>
,这是您可能想要也可能不想要的东西。
我有一个由多个具体实现的通用接口 class。例如:
public interface IMyInterface<T> {}
internal class Impl1 : IMyInterface<int> {}
internal class Impl2 : IMyInterface<float> {}
我想自动注册 IMyInterface<T>
的所有实现,以便我可以解析类型 T
支持的特定实现(在本例中,int
或 float
).例如:
class TheConsumer
{
// `impl` should resolve to `Impl1`
public TheConsumer(IMyInterface<int> impl) {}
}
根据我从 this github issue and the documentation 收集到的信息,似乎有两种机制可以做到这一点:
var builder = new ContainerBuilder();
// Mechanism 1
builder.RegisterAssemblyOpenGenericTypes(typeof(Startup).Assembly)
.AssignableTo(typeof(IMyInterface<>))
.AsImplementedInterfaces();
// Mechanism 2
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsClosedTypesOf(typeof(IMyInterface<>))
.AsImplementedInterfaces();
我只成功测试了上面显示的第二种机制。第一个我推测是一样的;但它可能不是。总的来说,我真的很困惑 Autofac 是如何处理“泛型”的。文档也没有提及 RegisterAssemblyOpenGenericTypes
,这无济于事。所以这是我的问题:
- 以上两个版本在功能上有什么区别?
- 在什么情况下你会选择其中之一?
- 什么是“开放”和“封闭”泛型(来自 Autofac 文档的术语)?
What is an "open" and "closed" generic (terminology from the Autofac documentation)?
开放泛型具有未定义的类型参数(例如 List<T>
)。然而,封闭的泛型具有定义的类型参数(例如 List<int>
)。
- What is the functional difference between the two versions above?
目前,您的两个实现都是 IMyInterface<T>
:
internal class Impl1 : IMyInterface<int> { }
internal class Impl2 : IMyInterface<float> { }
当您将 RegisterAssemblyOpenGenericTypes
(“机制 1”)与这些一起使用时,您会得到一个异常,即在解析 TheConsumer
时 IMyInterface<int>
未知。当您将 RegisterAssemblyTypes
与这些封闭的通用实现一起使用时,Impl1
在解析 TheConsumer
.
RegisterAssemblyOpenGenericTypes
的用法可以通过稍微扩展您的示例来说明。如果您添加 IMyInterface<T>
的另一个实现,例如:
internal class Impl3<T> : IMyInterface<T> { }
您知道 IMyInterface<T>
有一个“开放”的通用实现。因此,当您返回 RegisterAssemblyOpenGenericTypes
(“机制 1”)并尝试解析 TheConsumer
时,它起作用了,并且传入了 Impl3<int>
。
In what case would you choose one or the other?
将 RegisterAssemblyTypes
与您当前拥有的“封闭”泛型类型一起使用,IMyInterface<T>
的用户将只能解析使用该类型专门实现的接口(例如 IMyInterface<int>
由 Impl1
实现)。当您只想要在 IMyInterface<T>
.
当您实际上并不关心 IMyInterface<T>
中使用的类型参数是什么时,使用 RegisterAssemblyOpenGenericTypes
会很有用。这本质上只是允许更灵活地使用 IMyInterface<T>
,这是您可能想要也可能不想要的东西。