什么是在AutoMapper中为Map函数设置模拟预览的最佳方法.
我提取IMapper接口,以便我可以设置该接口的预期.我的映射器有依赖关系,所以我必须将它们传递给映射器.
当我创建2个mapper类实例时会发生什么,有2个不同的依赖实现?我认为两个映射器将使用相同的依赖项实例,因为AutoMapper映射是静态的.或者AutoMapper甚至可能会抛出异常,因为我尝试使用相同的对象设置2个不同的地图.
什么是解决这个问题的最佳方法?
public interface IMapper {
TTarget Map<TSource, TTarget>(TSource source);
void ValidateMappingConfiguration();
}
public class MyMapper : IMapper {
private readonly IMyService service;
public MyMapper(IMyService service) {
this.service = service
Mapper.CreateMap<MyModelClass, MyDTO>()
.ForMember(d => d.RelatedData, o => o.MapFrom(s =>
service.getData(s.id).RelatedData))
}
public void ValidateMappingConfiguration() {
Mapper.AssertConfigurationIsValid();
}
public TTarget Map<TSource, TTarget>(TSource source) {
return Mapper.Map<TSource, TTarget>(source);
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试将一个对象映射到另一个对象,但对象非常复杂.在开发过程中,我希望能够排除一堆字段并逐个访问它们,或者能够指定仅映射我想要的字段并在每次测试成功时增加它们.
所以:
class
string field1
string field2
string field3
Run Code Online (Sandbox Code Playgroud)
现在我想映射field1,测试,修复然后移动到field2那时field3.
这可能吗?
假设我有以下"目的地"类:
public class Destination
{
public String WritableProperty { get; set; }
public String ReadOnlyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和一个"source"类,ReadOnly其中一个属性的属性:
public class Source
{
public String WritableProperty { get; set; }
[ReadOnly(true)]
public String ReadOnlyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
很明显,但要明确:我将按照以下方式从一个Source类映射到另一个Destination类:
Mapper.Map(source, destination);
Run Code Online (Sandbox Code Playgroud)
配置Automapper以自动忽略属性ReadOnly(true)属性的方法有哪些?
我使用Automapper的Profile类进行配置.我不想弄脏具有Automapper特定属性的类.我不想为每个只读属性配置Automapper,并且通过这种方式导致大量重复.
IgnoreMap向属性添加属性: [ReadOnly(true)]
[IgnoreMap]
public String ReadOnlyProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)
我不想使用特定于自动化程序的属性来弄脏类并使其依赖于它.另外,我不想在属性中添加其他ReadOnly属性.
CreateMap<Source, Destination>()
.ForSourceMember(src => …Run Code Online (Sandbox Code Playgroud) 我已安装Automapper并AutoMapper.Extensions.Microsoft.DependencyInjection进入我的项目.我已将该行添加到ConfigureServices了Startup.cs.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
// . . .
services.AddAutoMapper();
}
Run Code Online (Sandbox Code Playgroud)
我还是得到一条红线services.AddAutoMapper().它说:
以下方法或属性之间的调用是不明确的:ServiceCollectionExtensions.AddAutoMapper(IServiceCollection,params Assembly [])和ServiceCollectionExtensions.AddAutoMapper(IServiceCollection,params Type [])
为什么会这样?所有的.NET Core都添加了我读过的自动提示指南,以这种方式实现.
我一直在将域对象展平为DTO,如下例所示:
public class Root
{
public string AParentProperty { get; set; }
public Nested TheNestedClass { get; set; }
}
public class Nested
{
public string ANestedProperty { get; set; }
}
public class Flattened
{
public string AParentProperty { get; set; }
public string ANestedProperty { get; set; }
}
// I put the equivalent of the following in a profile, configured at application start
// as suggested by others:
Mapper.CreateMap<Root, Flattened>()
.ForMember
(
dest => dest.ANestedProperty
, opt …Run Code Online (Sandbox Code Playgroud) 当AutoMapper遇到已经映射的对象时,它似乎再次使用该对象,而不是尝试重新映射它.我相信它是基于这样做的.Equals().
我有一棵正在映射的树.所以,一个具有一些属性的节点和子节点.不止一个节点具有相同的值.Equals(),因为它基于Id属性.节点的子节点是不同的,我需要重新映射,但它使用缓存的映射值.
有没有办法关闭缓存的映射?我能想到的只是实现一个新的转换器,但这完全违背了使用AutoMapper的目的.
这是一个如何重现的例子.
void Main()
{
var source = new List<Tag>
{
new Tag
{
Id = 1,
Name = "Tag 1",
ChildTags = new List<Tag>
{
new Tag
{
Id = 2,
Name = "Tag 2",
ChildTags = new List<Tag>
{
new Tag {Id = 3, Name = "Tag 3"},
new Tag {Id = 4, Name = "Tag 4"}
}
}
}
},
new Tag { Id = 1, Name = "Tag 1" }, …Run Code Online (Sandbox Code Playgroud) 我正在使用automapper来映射源和目标对象.当我映射它们时,我得到以下错误.
表达式必须解析为顶级成员.参数名称:lambdaExpression
我无法解决问题.
我的源和目标对象是:
public partial class Source
{
private Car[] cars;
public Car[] Cars
{
get { return this.cars; }
set { this.cars = value; }
}
}
public partial class Destination
{
private OutputData output;
public OutputData Output
{
get { return this.output; }
set { this.output= value; }
}
}
public class OutputData
{
private List<Cars> cars;
public Car[] Cars
{
get { return this.cars; }
set { this.cars = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
我必须Source.Cars用 …
背景:为了我自己的清晰度/自我教育,我试图使用TDD + DDD实现一个简单的订单输入应用程序.我的主要目标是通过分离问题来保持架构的清洁.
我有四层(现在)......
具有CustomerRepository类的Persistence/DAL,可以对"聚合根",客户及其相关订单和OrderItem执行GetById,Save,操作.为了让"穷人的依赖注入"
包含"业务实体"类的域/ BLL层,执行细粒度操作以帮助创建新订单,根据订单大小和客户位置应用税,折扣,装运逻辑.
应用程序Facade(应用程序服务/编排)包含大块,粗粒度的类来编排"业务实体"并减少与表示(可能是WebServices层)的聊天.
表示层
此外,我想在关键层之间传递POCO DTO ...特别是在Persistence => Domain层和ApplicationFacade => Presentation层之间.因此,我有CustomerDto,OrderDto,OrderItemDto以及在共享包中定义的适当关系.
我想使用Constructor Injection将ICustomerRepository的实现注入到Customer"业务实体"类中,然后在"业务实体"上调用Customer.Save()以启动创建/更新过程,最终调用Save方法CustomerRepository.毕竟,客户是"聚合根"并拥有保存所需的所有信息......它也是注入的CustomerRepository的"守护者".
问题: 这是我遇到麻烦的地方.我想保持Domain/BLL Layer尽可能纯,并避免将其耦合到任何第三方框架和API,但 Customer.Save()方法需要将Customer"聚合根"及其所有Orders和OrderItems转换为他们的DTO版本用于传输到注入的持久层CustomerRepository ...这是Automapper的工作.
问题是......如果我不把Automapper在域/ BLL层,我真的不知道哪里应该去.
将它放在ApplicationFacade中感觉不对,即使它的工作是编排.
把它放在Domain/BLL层中肯定是不对的,因为我想让它保持原始状态.
因此,我觉得我已经错过了一些东西......我正在接近这一点,因为他们对工作部分应该如何共同完成这项任务有着根本的误解.有什么建议?(请保持温和,我对这一切都是新手,对SO来说是新手.如果我需要展示一些我到目前为止的代码,请告诉我.)
我对使用Lazy加载功能的Linq to SQL非常感兴趣.而在我的项目,我用AutoMapper映射数据库模型域模型(从DB_RoleInfo到DO_RoleInfo).在我的存储库代码中如下:
public DO_RoleInfo SelectByKey(Guid Key)
{
return SelectAll().Where(x => x.Id == Key).SingleOrDefault();
}
public IQueryable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return from role in _ctx.DB_RoleInfo
select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
Run Code Online (Sandbox Code Playgroud)
SelectAll方法运行良好,但是当我调用时SelectByKey,我收到错误:
方法"RealMVC.Data.DO_RoleInfo MapDB_RoleInfo,DO_RoleInfo"无法转换为SQL.
Automapper是否完全不支持Linq?
我尝试了下面的手动映射代码而不是Automapper:
public IQueryable<DO_RoleInfo> SelectAll()
{
return from role in _ctx.DB_RoleInfo
select new DO_RoleInfo
{
Id = role.id,
name = role.name,
code = role.code
};
}
Run Code Online (Sandbox Code Playgroud)
这种方法按照我想要的方式工作.
有没有办法自动配置Automapper来扫描命名空间/程序集中的所有配置文件?我想要做的是从给定的程序集中过滤的给定程序集中将映射配置文件添加到AutoMapper,类似于StructureMap中的扫描约定:
public static void Configure()
{
ObjectFactory.Initialize(x =>
{
// Scan Assembly
x.Scan(
scanner =>
{
scanner.TheCallingAssembly();
scanner.Convention<MyCustomConvention>();
scanner.WithDefaultConventions();
});
// Add Registries
x.AddRegistry(new SomeRegistry());
});
Debug.WriteLine(ObjectFactory.WhatDoIHave());
}
public class MyCustomConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (!type.CanBeCastTo(typeof(IMyType)))
{
return;
}
string name = type.Name.Replace("SomeRubishName", String.Empty);
registry.AddType(typeof(IMyType), type, name);
}
Run Code Online (Sandbox Code Playgroud)
我试过使用SelfConfigure但找不到任何关于如何使用它来过滤配置文件的文档:
public static void Configure()
{
Mapper.Initialize(x =>
{
// My Custom profile
x.AddProfile<MyMappingProfile>();
// Scan Assembly
x.SelfConfigure(Assembly.GetCallingAssembly());
});
}
Run Code Online (Sandbox Code Playgroud)
另一个问题是我如何报告已经初始化的所有地图/配置文件(类似于StructureMap中的ObjectFactory.WhatDoIHave())?
automapper ×10
.net ×5
c# ×5
.net-core ×1
architecture ×1
asp.net-core ×1
asp.net-mvc ×1
automapper-2 ×1
flatten ×1
layer ×1
linq-to-sql ×1
mapping ×1
moq ×1
nested ×1
profile ×1
structuremap ×1