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创建目标类型,您需要配置两件事:
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的签名匹配)。问题是——你在做什么,为什么?也许如果我们有更多的背景,我们可以给你更好的建议。。。