3

我在 AutoMapper 4.2 上,我不知道为什么会出现这个错误

Autofac.Core.Registration.ComponentNotRegisteredException 请求的服务“Navigator.ItemManagement.Data.MappingProfiles.ReportPreferenceReportUserIdsResolver”尚未注册。为避免此异常,请注册组件以提供服务,使用 IsRegistered() 检查服务注册,或使用 ResolveOptional() 方法解决可选依赖项。

我的一个价值解析器收到此错误

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

此解析操作已结束。使用 lambda 注册组件时,无法存储 lambda 的 IComponentContext 'c' 参数。相反,要么从“c”再次解析 IComponentContext,要么解析基于 Func<> 的工厂以从中创建后续组件。

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

目标路径:ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]

源值:Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ---> AutoMapper.AutoMapperMappingException:

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

目标路径:ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]

4

2 回答 2

2

在遇到同样的问题后,我来到了这个问答环节。

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

o.ResolveUsing(new ReportPreferenceReportUserIdsResolver())

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

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

首先,确保您已使用 Autofac 注册您的IValueResolver类型,@LucianBargaoanu回答

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 实际执行时被释放。

于 2018-10-07T21:11:41.273 回答
-1

尝试

builder.RegisterType<ReportPreferenceReportUserIdsResolver>().AsSelf();
于 2017-08-04T06:35:49.083 回答