mik*_*ike 2 c# generics autofac
考虑以下类和接口:
interface IFactory<T>{}
class Factory<T> : IFactory<T>{ }
interface IEntity{}
class Entity : IEntity{ }
Run Code Online (Sandbox Code Playgroud)
我希望 Autofac 能够解决这样的IFactory<IEntity>问题Factory<Entity>:
b.RegisterType<Factory<Entity>>().As<IFactory<IEntity>>();
Run Code Online (Sandbox Code Playgroud)
但我得到以下异常(为了清楚起见缩写):
The type 'Factory`1[Entity]' is not assignable to service 'IFactory`1[[IEntity]]'
Run Code Online (Sandbox Code Playgroud)
这是为什么?如何解决这个问题?或者我正在尝试一些“错误”的事情?
我简单地研究了一下RegisterGeneric,但我认为它不适用于这里;另外,因为上面只是一个例子。在其他情况下,我可能想为IFactory<IEntity>.
这不是 Autofac 问题 - 这是通用方差问题。您会在简单的 C# 程序中看到完全相同的内容:
public class Program
{
public static void Main()
{
IFactory<IEntity> factory = new Factory<Entity>();
}
}
Run Code Online (Sandbox Code Playgroud)
大多数通用接口都是不变的——类型参数必须完全匹配。有些是协变的,例如IEnumerable<T>,允许您编写:
IEnumerable<object> objects = new List<string>();
Run Code Online (Sandbox Code Playgroud)
有些是逆变的,例如IComparer<T>,允许您编写:
IComparer<string> = Comparer<object>.Default;
Run Code Online (Sandbox Code Playgroud)
协变接口只允许它们的类型参数从实现中“出来”(例如通过返回类型)。逆变接口只允许它们的类型参数“进入”实现(例如通过常规参数)。当您拥有本身接受值等的委托参数时,它会变得微妙,但我们现在会忽略它......
听起来你IFactory<T>应该是协变的 - 所以你只需更改声明,如下所示:
interface IFactory<out T>{}
Run Code Online (Sandbox Code Playgroud)
到那时,代码就可以编译了,我希望Autofac 也能处理它。但这确实要求您的界面永远不会用作T输入。(我们无法判断,因为您没有显示任何接口成员。)
有关通用方差的更多详细信息,请参阅MS 文档。
| 归档时间: |
|
| 查看次数: |
1545 次 |
| 最近记录: |