gpt4 book ai didi

c# - 注册 AutoMapper ValueResolvers?

转载 作者:太空宇宙 更新时间:2023-11-03 16:59:38 26 4
gpt4 key购买 nike

我在使用 AutoMapper 4.2,但我无法弄清楚为什么会出现此错误

Autofac.Core.Registration.ComponentNotRegisteredException The requested service 'Navigator.ItemManagement.Data.MappingProfiles.ReportPreferenceReportUserIdsResolver' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

我的一个值解析器出现此错误

public class ReportPreferenceProfile : Profile
{
protected override void Configure()
{
CreateMap<ReportPreference, ReportPreferenceSummaryDto>()
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
.ForMember(d => d.Name, o => o.MapFrom(s => s.Name))
.ForMember(d => d.ReportUserIds, o => o.ResolveUsing<ReportPreferenceReportUserIdsResolver>());
}
}

public class ReportPreferenceReportUserIdsResolver : ValueResolver<IList<ReportUser>, IList<Guid>>
{
protected override IList<Guid> ResolveCore(IList<ReportUser> source)
{
return source.Select(r => r.UserId).ToList();
}
}

我已经在我的 Autofac 模块中注册了它

protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ReportPreferenceReportUserIdsResolver>().As<IValueResolver>();

//register all profile classes in the calling assembly
var profiles =
from t in typeof(Navigator.ItemManagement.Data.MappingProfiles.PlaceMapperProfile).Assembly.GetTypes()
where typeof(Profile).IsAssignableFrom(t)
select (Profile)Activator.CreateInstance(t);

builder.Register(context => new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}


})).AsSelf().SingleInstance();

builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve))
.As<IMapper>()
.SingleInstance();
}

更新 1

我尝试了 Lucian Bargaoanu 的建议并替换了

builder.RegisterType<ReportPreferenceReportUserIdsResolver>().As<IValueResolver>();

builder.RegisterType<ReportPreferenceReportUserIdsResolver>().AsSelf();

现在我得到的错误是

System.ObjectDisposedException

This resolve operation has already ended. When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentContext again from 'c', or resolve a Func<> based factory to create subsequent components from.

Mapping types: ReportPreference -> IList1
Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ->
System.Collections.Generic.IList
1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

Destination path: ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]

Source value: Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ---> AutoMapper.AutoMapperMappingException:

Mapping types: ReportPreference -> IList1
Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ->
System.Collections.Generic.IList
1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

Destination path: ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]

最佳答案

我遇到同样的问题后来到了这个问答。

正如@PeterRiesz 在评论中提到的,由于您的 IValueResolver 不需要任何依赖项,因此这里最简单的解决方案是更改连接值解析器的形式,以仅采用手动新实例:

o.ResolveUsing(new ReportPreferenceReportUserIdsResolver())

这不需要在 Autofac 容器中进行任何注册。

但是,您可能希望向其中注入(inject)服务,或者出于其他原因和可维护性而只想使用 Autofac 注册它。

首先,确保您已将 IValueResolver 类型注册为 @LucianBargaoanu answered 到 Autofac。 :

builder.RegisterType<ReportPreferenceReportUserIdsResolver>().AsSelf();

我以与您相同的方式定义我的 AutoMapper 注册,结果也遇到了与您在上面显示的相同的错误。

经过大量研究和反复试验自己解决错误后,我发现了这个 StackOverflow Q&A这让我朝着正确的方向前进。

您已经在此处为 AutoMapper 设置服务函数以用于解析依赖关系:

builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve))
.As<IMapper>()
.SingleInstance();

但是,正如错误所述,上下文 c 已在实际执行时被处理掉。解决这个问题的方法是重写 lambda 注册,如下所示:

builder.Register(c =>
{
//This resolves a new context that can be used later.
var context = c.Resolve<IComponentContext>();
var config = context.Resolve<MapperConfiguration>();
return config.CreateMapper(context.Resolve);
})
.As<IMapper>()
.SingleInstance();

还有一种注册服务解析器的方法。您可以在 MapperConfiguration 注册中执行此操作,而不是如下所示:

builder.Register(c =>
{
//Again, we must store a new instance of a component context for later use.
var context = c.Resolve<IComponentContext>();
var profiles = c.Resolve<IEnumerable<Profile>>();

return new MapperConfiguration(x =>
{
foreach (var profile in profiles)
{
x.AddProfile(profile);
}

//Registering the service resolver method here.
x.ConstructServicesUsing(context.Resolve);
});
})
.SingleInstance()
.AsSelf();

这两个似乎是等价的。我个人认为后者更清洁。

这里要注意的是,需要在顶层 lambda 中解析一个新的上下文,因为传入的实例将在 lambda 实际执行时被释放。

关于c# - 注册 AutoMapper ValueResolvers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45497060/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com