c# - Automapper & Autofac typeconverter - 没有默认构造函数

标签 c# automapper autofac

我在将 aufotac 注入(inject)我的 autopmapper 类型转换器时遇到问题。我尝试了一些不同的方法,但我目前无法使用下面的代码。我最接近找到解决方案的是下面的代码(从 http://thoai-nguyen.blogspot.se/2011/10/autofac-automapper-custom-converter-di.html 借用了一小部分)。他的样本似乎以 1:1 的比例工作,但无法找到我遗漏的地方。像往常一样提取相关位,如果不足请告诉我。

我的 autofac Bootstrap :

public class AutoFacInitializer
    {
        public static void Initialize()
        {
            //Mvc
            var MvcContainer = BuildMvcContainer();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(MvcContainer));

            //Web API
            var ApiContainer = BuildApiContainer();
            var ApiResolver = new AutofacWebApiDependencyResolver(ApiContainer);
            GlobalConfiguration.Configuration.DependencyResolver = ApiResolver;
        }

        private static IContainer BuildApiContainer()
        {
            var builder = new ContainerBuilder();
            var assembly = Assembly.GetExecutingAssembly();
            builder.RegisterApiControllers(assembly);
            return BuildSharedDependencies(builder, assembly);
        }

        private static IContainer BuildMvcContainer()
        {
            var builder = new ContainerBuilder();
            var assembly = typeof (MvcApplication).Assembly;
            builder.RegisterControllers(assembly);
            builder.RegisterFilterProvider();
            return BuildSharedDependencies(builder, assembly);
        }

        private static IContainer BuildSharedDependencies(ContainerBuilder builder, Assembly assembly)
        {
            //----Build and return container----
            IContainer container = null;

            //Automapper
            builder.RegisterAssemblyTypes(assembly).AsClosedTypesOf(typeof(ITypeConverter<,>)).AsSelf();
            AutoMapperInitializer.Initialize(container);
            builder.RegisterAssemblyTypes(assembly).Where(t => typeof(IStartable).IsAssignableFrom(t)).As<IStartable>().SingleInstance();

            //Modules
            builder.RegisterModule(new AutofacWebTypesModule());
            builder.RegisterModule(new NLogLoggerAutofacModule());

            //Automapper dependencies
            builder.Register(x => Mapper.Engine).As<IMappingEngine>().SingleInstance();

            //Services, repos etc
            builder.RegisterGeneric(typeof(SqlRepository<>)).As(typeof(IRepository<>)).InstancePerDependency();
            
            container = builder.Build();
            return container;
        }
    }

我的 Automap Bootstrap /初始化程序:

namespace Supportweb.Web.App_Start
{
    public class AutoMapperInitializer
    {
        public static void Initialize(IContainer container)
        {
            Mapper.Initialize(map =>
            {
                map.CreateMap<long?, EntityToConvertTo>().ConvertUsing<LongToEntity<NavigationFolder>>();

                map.ConstructServicesUsing(t => container.Resolve(t)); 
            });
            Mapper.AssertConfigurationIsValid();
        }
    }
}

我试图开始工作的类型转换器:

public class LongToEntity<T> : ITypeConverter<long?, T>
    {
        private readonly IRepository<T> _repo;

        public LongToEntity(IRepository<T> repo)
        {
            _repo = repo;
        }

        public T Convert(ResolutionContext context) 
        {
            long id = 0;
            if (context.SourceValue != null)
                id = (long)context.SourceValue;
            return _repo.Get(id);
        }
    }

除了转换器,所有映射都工作正常。该错误似乎表明我缺少 ioc 引用,但我已经尝试过,但提到的 ITypeConverter<,> 和 LongToEntity<> 以及似乎没有帮助的变体。

最佳答案

您当前的代码存在三个问题:

  1. 您需要调用 ConstructServicesUsing 之前按照链接文章中的描述注册任何映射:

    The tricky thing is we need to call that method before we register mapper classes.

    所以正确的 Mapper.Initialize是以下内容:

    Mapper.Initialize(map =>
            {
                map.ConstructServicesUsing(t => container.Resolve(t));  
    
                map.CreateMap<long?, EntityToConvertTo>()
                    .ConvertUsing<LongToEntity<NavigationFolder>>();
            });
    
  2. 因为您的 LongToEntity<T>是一个开放的泛型,您不能使用 AsClosedTypesOf但你还需要在这里使用 RegisterGeneric注册:

    所以改变你的ITypeConverter<,>注册自:

     builder.RegisterAssemblyTypes(assembly)
            .AsClosedTypesOf(typeof(ITypeConverter<,>)).AsSelf();
    

    使用RegisterGeneric方法:

     builder.RegisterGeneric(typeof(LongToEntity<>)).AsSelf();
    
  3. 因为您已将 Automapper 初始化移动到一个单独的方法中 AutoMapperInitializer.Initialize您不能使用文章中的 clojure 技巧,因此您需要在创建容器后调用它:

     container = builder.Build();
     AutoMapperInitializer.Initialize(container);
     return container;
    

关于c# - Automapper & Autofac typeconverter - 没有默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17772281/

相关文章:

c# - foreach抛出异常,为什么?

c# - 使用 AutoMapper 自定义映射

c# - 如何在 Automapper 6 映射期间忽略所有源成员的空值?

c# - 使用 Autofac 进行属性注入(inject)的正确方法

c# - 参数化实例化如何与单实例生命范围一起工作

C# 目录到 "play with"

c# 约束在泛型类型的扩展中被忽略

c# - 保存计时器高分

C#:如何使自动映射器映射类型对象的属性?

c# - Autofac、单元测试、C# - Autofac Moq 和 FakeItEasy 集成包之间的区别