我是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
。
很抱歉很长的解释。我希望有人可以帮助我开展工作!
谢谢。
答案 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
{
}