带有嵌套开放泛型的Autofac

本文关键字:泛型 Autofac 嵌套 | 更新日期: 2024-09-22 17:01:17

我是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传递。

抱歉解释太长。我希望有人能帮我把这件事做好!

谢谢。

带有嵌套开放泛型的Autofac

您所要做的似乎只是将打开的通用注册拆分为两个单独的注册,如下所示:

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
{
}