具有嵌套开放式泛型的Autofac

时间:2016-04-16 14:24:15

标签: c# .net generics autofac

我是Autofac的新手,在解决嵌套的开放式通用服务类型方面遇到了一些麻烦。

我希望我的ContactService实现两个接口。两个接口都使用相同的泛型类型参数,但第二个接口是嵌套的:

class ContactService<TParent>
    : IContactService<TParent>,
      IFeatureProvider<ContactFeature<TParent>>
    where TParent : class, IDomainModel
{ }

如果我这样做:

builder
    .RegisterGeneric(typeof(ContactService<>))
    .As(typeof(IContactService<>))
    .As(typeof(IFeatureProvider<>);

然后尝试解析服务IFeatureProvider<ContactFeature<Household>>(例如)导致Autofac尝试实例化

ContactService<ContactFeature<Household>>

而不是

ContactService<Household>

我理解为什么以上不起作用。所以我试着这样做了:

builder
    .RegisterGeneric(typeof(ContactService<>))
    .As(typeof(IContactService<>))
    .As(typeof(IFeatureProvider<>)
        .MakeGenericType(typeof(ContactFeature<>)));

但是,我仍然遇到类似的错误:

TypeLoadException: GenericArguments[0], 'ContactFeature`1[Household]', 
  on 'Contact`1[TParent]' violates the constraint of type parameter 'TParent'.

System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, 
  Int32 numGenericArgs, ObjectHandleOnStack type)

ArgumentException: GenericArguments[0], 'ContactFeature`1[Household]', 
  on 'IContactService`1[TParent]' violates the constraint of type 'TParent'.

System.RuntimeType.ValidateGenericArguments(MemberInfo definition, 
  RuntimeType[] genericArguments, Exception e)

看起来Autofac正试图将ContactFeature<Household>作为TParent传递而不只是Household

很抱歉很长的解释。我希望有人可以帮助我开展工作!

谢谢。

1 个答案:

答案 0 :(得分:1)

您似乎要做的就是将开放式通用注册拆分为2个单独的注册,例如:

var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(ContactService<>))
    .As(typeof(IContactService<>));

builder.RegisterGeneric(typeof(ContactService<>))
    .As(typeof(IFeatureProvider<>));

var container = builder.Build();

var service = container.Resolve(typeof(IFeatureProvider<ContactFeature<Household>>));
var service2 = container.Resolve(typeof(IContactService<Household>));

Console.WriteLine(service.GetType());
Console.WriteLine(service2.GetType());

Console.ReadKey();

两个结果都会为您提供ContactService<Household>的实例。但说实话,我不知道为什么它单独工作,并且当你在单一注册中将它组合在一起时不起作用。

我使用以下类和接口来测试解决方案:

class ContactService<TParent> : IContactService<TParent>, IFeatureProvider<ContactFeature<TParent>>
    where TParent : class, IDomainModel
{
}

interface IContactService<T> where T : class, IDomainModel
{
}

interface IFeatureProvider<TProvider>
{
}

interface IDomainModel
{
}

class Household : IDomainModel
{
}

class ContactFeature<TDomainModel> where TDomainModel: class, IDomainModel
{
}