C# 使用AutoMapper和DI容器实例化类型

C# 使用AutoMapper和DI容器实例化类型,c#,dependency-injection,automapper,castle-windsor,xamarin,prism,C#,Dependency Injection,Automapper,Castle Windsor,Xamarin,Prism,请参阅下面的代码: public class Test : ITest { public ITest2 _iTest2; public int _id; public string _name; public Test(ITest2 test2) { _iTest2 = test2; } } public interface ITest {

请参阅下面的代码:

public class Test : ITest
    {
        public ITest2 _iTest2;
        public int _id;
        public string _name;

        public Test(ITest2 test2)
        {
            _iTest2 = test2;
        }
    }

    public interface ITest
    {
    }

    public class Test2 : ITest2
    {
    }

    public interface ITest2
    {

    }

    public class Test3 : ITest3
    {
        public int _id;
        public string _name;
    }

    public interface ITest3
    {

    }
我的Global.asax中有以下内容:

Mapper.Initialize(m =>
            {  
 m.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
});
Mapper.Initialize(m=>
{  
m、 CreateMap().ConstructUsing(opt=>newBusinessLayer.Test(newBusinessLayer.Test2());
});
我可以在我的客户端应用程序中映射以下类型:

cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
 public void Install(IWindsorContainer container, IConfigurationStore store)
    {

        container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn(typeof(IValueResolver<,,>)));
        // container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());
        container.Register(Types.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
        var profiles = container.ResolveAll<Profile>();

        // Add your list of profiles to the mapper configuration here
        Mapper.Initialize(m => {
            m.ConstructServicesUsing(container.Resolve);
            profiles.ToList().ForEach(p => m.AddProfile(p));
        });

        // I'm not sure about this as I haven't used AutoMapper for a while,
        // but I assume you want to resolve the static mapper instance
        container.Register(Component.For<IMapper>().Instance(Mapper.Instance));
    }
cfg.CreateMap().ConstructUsing(opt=>newBusinessLayer.Test(newBusinessLayer.Test2());
如何使用Castle Windsor映射类型,而不必为Test和Test2使用new关键字

我读了另一个答案,有人建议这样做:

cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
 public void Install(IWindsorContainer container, IConfigurationStore store)
    {

        container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn(typeof(IValueResolver<,,>)));
        // container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());
        container.Register(Types.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
        var profiles = container.ResolveAll<Profile>();

        // Add your list of profiles to the mapper configuration here
        Mapper.Initialize(m => {
            m.ConstructServicesUsing(container.Resolve);
            profiles.ToList().ForEach(p => m.AddProfile(p));
        });

        // I'm not sure about this as I haven't used AutoMapper for a while,
        // but I assume you want to resolve the static mapper instance
        container.Register(Component.For<IMapper>().Instance(Mapper.Instance));
    }
public void安装(IWindsorContainer,IConfigurationStore)
{
Register(Types.fromsassembly(Assembly.getExecutionGassembly()).BasedOn(typeof(IValueResolver));
//Register(Types.fromsassembly(Assembly.getExecutionGassembly()).BasedOn());
container.Register(type.fromthissembly().BasedOn().WithServiceBase());
var profiles=container.ResolveAll();
//在此处将配置文件列表添加到映射器配置
Mapper.Initialize(m=>{
m、 ConstructionServiceSusing(container.Resolve);
profiles.ToList().ForEach(p=>m.AddProfile(p));
});
//我不确定,因为我已经有一段时间没用AutoMapper了,
//但是我假设您想要解析静态映射器实例
Register(Component.For().Instance(Mapper.Instance));
}
我是否必须这样做:

cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
cfg.CreateMap().ConstructUsing(opt=>newBusinessLayer.Test(newBusinessLayer.Test2());
或者AutoMapper是否能够使用以下方法映射类型:

cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>()
cfg.CreateMap()

为了让AutoMapper使用Windsor创建目标类型,您需要配置两件事:

  • 告诉AutoMapper使用Windsor构建服务
  • 告诉AutoMapper(每个映射)实际使用上述配置

     var container = new WindsorContainer();
    
        Mapper.Initialize(m =>
        {
            m.ConstructServicesUsing(container.Resolve);
    
            m.CreateMap<Test3, ITest>().ConstructUsingServiceLocator(); // This is important!
    
        });
    
        container.Register(Component.For<ITest>().ImplementedBy<Test>());
        container.Register(Component.For<ITest2>().ImplementedBy<Test2>());
        container.Register(Component.For<ITest3>().ImplementedBy<Test3>());
    
        var test3 = new Test3();
        var test1 = Mapper.Instance.Map<Test3, ITest>(test3);
    
    var容器=新的WindsorContainer();
    Mapper.Initialize(m=>
    {
    m、 ConstructionServiceSusing(container.Resolve);
    m、 CreateMap().ConstructUsingServiceLocator();//这很重要!
    });
    container.Register(Component.For().ImplementedBy());
    container.Register(Component.For().ImplementedBy());
    container.Register(Component.For().ImplementedBy());
    var test3=新的test3();
    var test1=Mapper.Instance.Map(test3);
    

  • 对于任何需要使用3.6、7.1和8.1的人来说,这对我来说是有效的

    在App.xml.cs文件中

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
            {
    /// other registrations ...
    
                containerRegistry.RegisterSingleton<IMapperProvider, MapperProvider>();
                containerRegistry.RegisterInstance(typeof(IMapper), GetMapper(containerRegistry));
     }
    
            /// <summary>
            /// This function required in order for injection into custom automapper resolvers
            /// </summary>
            private IMapper GetMapper(IContainerRegistry container)
            {
                var mp = container.GetContainer().Resolve<IMapperProvider>(new[] { container });
                return mp.GetMapper();
            }
    
    受保护的覆盖无效注册表类型(IContainerRegistry containerRegistry)
    {
    ///其他注册。。。
    containerRegistry.RegisterSingleton();
    RegisterInstance(typeof(IMapper)、GetMapper(containerRegistry));
    }
    /// 
    ///此功能是注入自定义automapper解析器所必需的
    /// 
    专用IMapper GetMapper(IContainerRegistry容器)
    {
    var mp=container.GetContainer().Resolve(新[]{container});
    返回mp.GetMapper();
    }
    
    映射程序提供程序如下所示:

    public class MapperProvider : IMapperProvider
        {
            private readonly IContainerRegistry _container;
    
            public MapperProvider(IContainerRegistry container)
            {
                _container = container;
            }
    
            public IMapper GetMapper()
            {
                var config = new MapperConfiguration(cfg =>
                {
                    cfg.ConstructServicesUsing(t => _container.GetContainer().Resolve(t));
                    // any custom profile statement such as
                    cfg.AddProfile<MappingSourcesProfile>();
                    // ....
                });
    
                return config.CreateMapper();
            }
        }
    
    公共类MapperProvider:IMapperProvider
    {
    专用只读IContainerRegistry容器;
    公共MapperProvider(IContainerRegistry容器)
    {
    _容器=容器;
    }
    公共IMapper GetMapper()
    {
    var config=new-MapperConfiguration(cfg=>
    {
    ConstructServicesUsing(t=>_container.GetContainer().Resolve(t));
    //任何自定义概要文件语句,例如
    AddProfile();
    // ....
    });
    返回config.CreateMapper();
    }
    }
    
    现在,我的自定义解析器可以工作,例如:

        public class BarcodesResolver : IValueResolver<repo.Book, Book, List<Barcode>>
        {
            private readonly IMapper _mapper;
    
            public BarcodesResolver(IMapper mapper)
            {
                _mapper = mapper;
            }
    
            public List<Barcode> Resolve(repo.Book source, Book destination, List<Barcode> destMember, ResolutionContext context)
            {
                repo.BookAttributes groupedAttribs = JsonConvert.DeserializeObject<repo.BookAttributes>(source.BookAttributes);
    
                return _mapper.Map<List<repo.Barcode>, List<Barcode>>(groupedAttribs.Barcodes);
            }
        }
    
    公共类条形码解析程序:IValueResolver
    {
    专用只读IMapper\u映射器;
    公共条形码解算器(IMapper映射器)
    {
    _映射器=映射器;
    }
    公共列表解析(repo.Book源、图书目的地、列表目的地成员、解析上下文)
    {
    repo.BookAttributes groupedAttribs=JsonConvert.DeserializeObject(source.BookAttributes);
    返回_mapper.Map(groupedAttribs.Barcode);
    }
    }
    
    这里要解决的困难部分是如何指定需要将containerRegistry传递到MapperProvider的构造函数中。也许有更好的方法可以做到这一点,但至少这是可行的


    同时到达行
    cfg.ConstructServicesUsing(t=>_container.GetContainer().Resolve(t))相当模糊,因为似乎没有几个示例。

    代码所说的是“当您想要创建新服务时,请从Windsor容器中获取”。不使用类似的东西可能是最好的办法。@stuartd,需要什么自动映射器配置才能使上面的代码正常工作,即Castle Windsor和AutMapper?对不起,我上次使用Castle已经太久了,记不起来了。@stuartd,你能回答我原版pimost最后五行中的问题吗?你能解释一下你在这里想做什么吗?这只是测试代码吗?您将控制器映射到控制器的目的是什么?我已经试过了,我的测试代码运行良好:-这使用了您发布的确切的
    ITest
    etc接口和类。您需要使用
    ConstructServicesUsing
    进行映射时,使用
    Func
    尝试从容器解析对象(与
    IWinsorContainer.resolve的签名匹配)。问题是——你在做什么,为什么?也许如果我们有更多的背景,我们可以给你更好的建议。。。