使用AutoFac注入通用类型参数 [英] Injecting Generic type parameters with AutoFac

查看:460
本文介绍了使用AutoFac注入通用类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我对使用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";
    }
}

创建一个通用类PersonH​​andler来处理不同类型的人,并且希望PersonH​​andler在适当的时间实例化该人,因此我不希望注入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注入通用类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆