问题描述
我认为我对使用AutoFac可以做什么感到非常困惑,有人可以让我步入正轨.
I think I am really confused about what I can do with AutoFac, can someone please put me on track.
我有基本类型
class PersonBase{
public string SaySomething(){
return "I am base";
}
}
我得到两个具体的类
class FakePerson : PersonBase{
public override string SaySomething(){
return "I'm so Fake";
}
}
class RealPerson : PersonBase{
public override string SaySomething(){
return "I am For Real";
}
}
创建一个通用类PersonHandler来处理不同类型的人,并且希望PersonHandler在适当的时间实例化该人,因此我不希望注入Person的实例,只需要派生类型
Create a generic class, PersonHandler, to deal with different types of people and would like the PersonHandler to instantiate the person at the appropriate time, so I do not want an instance of Person injected, just need to derived type
class PersonHandler<T>
where T : PersonBase, new() {
T _Person;
public DoWork(){
_Person = new T();
_Person.SaySomething();
}
}
现在,在注册了下面详细介绍的类型之后,我会尝试使用处理程序,结果会有所不同.
Now I try to use the handler, after registering the types as detailed next, with varying results.
var ph = contrainer.Resolve<PersonHandler<PersonBase>>();
ph.DoWork();
我试图按如下方式注册类型
I attempted to register the types as follows
1. vBuilder.RegisterType<PersonHandler<FakePerson>>().As<PersonHandler<PersonBase>>();
这给我一个错误,指出不能将PersonHandler<FakePerson>
分配给PersonHandler<PersonBase>
(或者相反,我不能重新分配该值)
This gives me an error stating the PersonHandler<FakePerson>
is not assignable to PersonHandler<PersonBase>
(or the other way around I don't recal which)
2. vBuilder.RegisterGeneric<typeof(PersonHandler<>)>
vBuilder.RegisterType<FakePerson>().As<PersonBase>();
这不能将PersonBase
解析为FakePerson
,而只是给出PersonHandler<PersonBase>
,因此结果为我是基础"
This does not resolve PersonBase
to FakePerson
, but just gives PersonHandler<PersonBase>
, So it results in "I am Base"
3. vBuilder.RegisterGeneric(typeof(PersonHandler<FakePerson>)).As(typeof(PersonHandler<PersonBase>));
这给出了一个错误,指出PersonHandler<FakePerson>
不是开放类型
This given an error saying that PersonHandler<FakePerson>
is not an open type
所以现在我整天都在追寻自己的故事,坦率地说,它变得越来越乏味,
So now I have been chasing my tale all day and, frankly, it is getting quit tedious,
请帮助
推荐答案
(几乎)正确的解决方案是您已经尝试过的解决方案:
The (almost) correct solution is this one that you already tried:
builder.RegisterType<PersonHandler<FakePerson>>()
.As<PersonHandler<PersonBase>>();
Autofac给您一个错误的原因是C#中的通用类类型无法按这种方式工作.
The reason Autofac gave you an error is that generic class types in C# don't work this way.
也就是说,你不能写:
PersonHandler<PersonBase> ph = new PersonHandler<FakePerson>();
(在您的IDE中尝试一下-编译器将拒绝它.)
(Give it a try in your IDE - the compiler will reject it.)
这样做的原因是,C#4中添加的必需功能矛盾性仅支持接口类型.
The reason for this is that contravariance, the required feature added in C#4, only supports interface types.
简而言之,如果您创建IPersonHandler<T>
并将其用作服务,则上面的代码将按预期工作:
To cut a long story short, if you create IPersonHandler<T>
and use that as the service then the above code will work as expected:
interface IPersonHandler<in T>
where T : PersonBase, new() {
void DoWork();
}
请注意接口声明上的in
参数.
Note the in
parameter on the interface declaration.
使PersonHandler<T>
实现IPersonHandler<T>
:
class PersonHandler<T> : IPersonHandler<T>
where T : PersonBase, new() {
然后像这样注册:
builder.RegisterType<PersonHandler<FakePerson>>()
.As<IPersonHandler<PersonBase>>();
然后您可以使用以下方法获取处理程序:
You can then get handlers using:
IPersonHandler<PersonBase> handler =
container.Resolve<IPersonHandler<PersonBase>>();
返回的handler
对象的类型将为PersonHandler<FakePerson>
.
The returned handler
object will be of type PersonHandler<FakePerson>
.
这篇关于使用AutoFac注入通用类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!