我正在尝试使用ValueInjector来压缩一个类,并让它同时复制值Nullable<int>'s到int的.
例如,给出以下(人为)课程:
class CustomerObject
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public OrderObject OrderOne { get; set; }
}
class OrderObject
{
public int OrderID { get; set; }
public string OrderName { get; set; }
}
class CustomerDTO
{
public int? CustomerID { get; set; }
public string CustomerName { get; set; }
public int? OrderOneOrderID { get; set; }
public string OrderOneOrderName { get; set; } …Run Code Online (Sandbox Code Playgroud) 我正在研究一个DDD项目,其中正在进行大量的字段映射.我正在寻找一个快速而可靠的映射库,而不是手工编写所有映射,并且似乎有很多选项.
目前我更倾向于Glue,因为它看起来提供了相当多的功能,并且还考虑了单元测试,这对我正在进行的项目也很重要.在不利方面,它只下载了200多次,这让我觉得像ValueInjecter这样的东西可能是更好的选择,因为它有更多的支持.
我的问题是,Glue比其他任何一个地图制作者更好还是更差?或者上面提到的映射器之间的差异在性能和可用性方面可以忽略不计?
是否可以在2个不同的枚举之间进行映射?
也就是说,我想获取一个枚举值并将其映射到不同枚举类型中的相应值.
我知道如何使用AutoMapper执行此操作:
// Here's how to configure...
Mapper.CreateMap<EnumSourceType, EnumTargetType>();
// ...and here's how to map
Mapper.Map<EnumTargetType>(enumSourceValue)
Run Code Online (Sandbox Code Playgroud)
但我是ValueInjecter的新手,无法弄明白.
**更新**
源和目标枚举类型类似于:
public enum EnumSourceType
{
Val1 = 0,
Val2 = 1,
Val3 = 2,
Val4 = 4,
}
public enum EnumTargetType
{
Val1,
Val2,
Val3,
Val4,
}
Run Code Online (Sandbox Code Playgroud)
因此,常量具有相同的名称,但值不同.
我使用的是 ValueInjecter 而不是 AutoMapper。我正在尝试使用
.InjectFrom<UnflatLoopValueInjection>(model)
Run Code Online (Sandbox Code Playgroud)
它有效,但我还想指定一些在 unflattening 操作期间要忽略的属性,例如编写如下内容:
.InjectFrom<UnflatLoopValueInjection>(new IgnoreProperties("Prop1", "Prop2"), model)
Run Code Online (Sandbox Code Playgroud)
或者
.InjectFrom<UnflatLoopValueInjection>(model).IgnoreProperties("Prop1", "Prop2")
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
在ValueInjecter的旧版本(版本2.3)中,我创建了扩展ConventionInjection的类,以便控制匹配的属性-这使我能够执行以下操作:
public class UnderscoreInjector : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Type == c.TargetProp.Type
&& c.SourceProp.Name.Replace("_", "") == c.TargetProp.NameReplace("_", "");
}
}
Run Code Online (Sandbox Code Playgroud)
忽略名称中的下划线(在您必须处理一些旧的,名称奇怪的业务对象并且不想让奇怪的名称冒泡到您的核心代码中时很有用)
在最新版本3.1中,我只能通过子类化LoopInjection或PropertyInjection类来找到一种自定义类型匹配的方法:
protected override bool MatchTypes(Type source, Type target)
{
return source == typeof(int) && target.IsSubclassOf(typeof(Enum));
}
Run Code Online (Sandbox Code Playgroud)
在这些类中,如果我想更改属性名称的映射方式,似乎没有明显的要重写的地方。
我可以看到在3.1中,我们可以为特定字段定义自定义地图:
Mapper.AddMap<Customer, CustomerInput>(src =>
{
var res = new CustomerInput();
res.InjectFrom(src); // maps properties with same name and type
res.FullName = src.FirstName + " " + src.LastName;
return res;
});
Run Code Online (Sandbox Code Playgroud)
但这不是基于约定的,因此您必须手动操作所有不理想的字段
ConventionInjection类发生了什么?它是否刚刚被重命名,或者有其他方法可以在最新版本中创建这些类型的自定义映射?
是否可以使用AutoMapper来填充另一个对象的详细信息?例如(假设先前的配置):
var foo = new Foo { PropA = "", PropB = "Foo" };
var bar = new Bar { PropA = "Bar", PropB = "" };
Mapper.Map<Foo, Bar>(foo, bar);
Console.WriteLine(bar.PropB); //Returns "Foo"
Run Code Online (Sandbox Code Playgroud)
只是想知道是否有人尝试过这种奇怪的映射用法,这更像是将一个对象的匹配数据合并到另一个对象中.
提前致谢!
更新:
对于这种情况,看起来ValueInjector也更合适.在StackOverflow上已经对AutoMapper与ValueInjecter的适当用法进行了一些很好的讨论.
我需要从NHibernate POCO对象创建DTO.问题是POCO对象包含动态代理,不应将其复制到DTO.我急切地加载我需要提前传输的所有集合和引用,我不希望NHibernate开始加载我没有提前加载的引用集合.
关于SO的几个类似问题得到了答案:
在我的情况下,第一个建议是无关紧要的,因为根据我的理解,它导致急切的加载来替换代理.实际上,它甚至不起作用 - 它不会删除我的对象中的代理.(任何解释为什么?)
第二个建议,关闭延迟加载似乎导致所有引用和集合急切加载,基本上加载整个数据库.我的期望是,如果延迟加载,我没有请求集合,它将不会被加载.(我是否认为NHibernate没有这样的选择?)
我正在使用NHibernate 3.3.1和流畅的配置.
重申我的主要问题,我需要创建DTO清理代理,从包含代理的POCO复制,我不想加载这些代理背后的数据.
任何有用的建议,包括示例代码,并使用ValueInjecter/AutoMapper自动化过程将非常有帮助.
编辑#1:
遵循Roger Alsing建议使用投影,我意识到我实际上正在寻找的是类似于ValueInjecter的基于约定的映射.这就是原因.最初,我的DTO定义与模型的POCO相同.这是由于代码库很大,这取决于在客户端项目上传输的现有POCO.
使用投影,我将必须指定必须复制哪个字段子集,并且该子集在每个上下文中可能不同(理想情况下,DTO会有所不同).这意味着当应该有第二个选项时,会向服务器端引入许多新代码.
使用ValueInjecter,我将能够在一次调用中按惯例填充DTO,而无需编写特定的预测,或者必须将这些预测保留在未来.也就是说,如果我能够让ValueInjecter忽略代理对象.
鉴于在我的情况下使用投影是一个很好但不理想的解决方案,有没有办法配置像ValueInjecter这样的东西来复制POCO而无需复制代理或在副本上触发急切/延迟加载?
鉴于3个班级,
A和B各有一个ID属性,然后是各种其他属性
和C,它有一个ID,以及A和B的组合属性,
我想要
C.InjectFrom(A);
C.InjectFrom(B);
Run Code Online (Sandbox Code Playgroud)
这样A中的ID就会被保留,而不会被B覆盖.
显然在这个简单的情况下,我可以颠倒两个调用的顺序,但在我的真实世界的例子中,它稍微复杂一点,我不能只通过排序来解决问题.
基本上我希望第二次注射忽略第一次注射已经处理过的任何事情,这可能会继续进行几次注射.这些注射中的一些也可以来自相同的物体
C.InjectFrom(A);
C.InjectFrom<SomeInjector>(A);
C.InjectFrom<SomeInjector2>(A);
C.InjectFrom<SomeInjector3>(A);
Run Code Online (Sandbox Code Playgroud)
等等
我正在使用Value Injecters使用LoopValueInjection从1种类型映射到另一种类型,并使用一些自定义逻辑覆盖SetValue(对象v)方法.我试图检测何时传入HashSet并通过HashSet并将方法应用于其中的每个项目以进行一些清理.我遇到的问题是因为参数只是一个对象,我不知道HashSet中的项目类型.例如,它可以是HashSet或HashSet.
这是我目前的代码,但我得到一个InvalidCastException.
protected override object SetValue(object v)
{
if (type.Name == "HashSet`1")
{
var genericType = type.GetGenericArguments()[0];
// this line throws the InvalidCastException
var cleanHashSet = (HashSet<object>)Activator.CreateInstance(type);
foreach (var item in (HashSet<object>)v) // I'm sure this cast will throw as well
{
cleanHashSet.Add(Clean(item));
}
return cleanHashSet;
}
return base.SetValue(v);
}
Run Code Online (Sandbox Code Playgroud)
我想主要的问题是,一旦我确定它实际上是某种HashSet,我怎么能循环通过作为对象传入的HashSet?我也在想我将需要创建一个特定类型的新空HashSet,这样我就可以将每个被清理的项目放入其中.
valueinjecter ×10
c# ×8
automapper ×4
.net ×1
asp.net ×1
dto ×1
enums ×1
mapper ×1
mapping ×1
nhibernate ×1
poco ×1
reflection ×1