注册AutoMapper ValueResolvers?

时间:2017-08-04 01:47:03

标签: c# autofac automapper-4

我在AutoMapper 4.2上,我无法弄清楚为什么我会收到此错误

  

Autofac.Core.Registration.ComponentNotRegisteredException   要求的服务   ' Navigator.ItemManagement.Data.MappingProfiles.ReportPreferenceReportUserIdsResolver'   尚未注册。要避免此异常,请注册a   组件提供服务,检查服务注册使用   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

     

此解析操作已经存在   结束。使用lambdas注册组件时,   IComponentContext&#39; c&#39;无法存储lambda的参数。   相反,要么从&#39; c&#39;再次解析IComponentContext,要么解析   FUNC&LT;&GT;基于工厂从中创建后续组件。

     

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

     

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

     

来源价值:   Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ---&gt;   AutoMapper.AutoMapperMappingException:

     

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

     

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

2 个答案:

答案 0 :(得分:0)

遇到相同的问题后,我进行了问答。

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

o.ResolveUsing(new ReportPreferenceReportUserIdsResolver())

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

但是,您可能希望将服务注入其中,或者出于其他原因和可维护性而只想在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中解析新的上下文。

答案 1 :(得分:-1)

尝试

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