有时,在处理数据传输对象(例如从数据库或csv文件中检索)时,编写一些辅助函数来移动数据会很不错。
例如:
class MyDto
{
public string Name { get; set; }
}
class MyBusinessObject
{
public string Name { get; set;}
}
我想写一些类似的东西:
MyDto source;
MyBusinessObject target;
var hasChanged = target.Set(source, source => source.Name, target => target.Name); // lamdba expressions, or whatever it takes to make it work
使用扩展方法:
public static bool Set<TS, TT, TValue>(this TS source, IGetProperty<TS, TValue> sourceGetProperty, IGetOrSetProperty<TT, TValue> targetGetOrSetProperty)
{
var sourceValue = sourceGetProperty.Invoke(source);
var actualValue = targetGetOrSetProperty.Invoke(target);
if(sourceValue != actualValue)
{
targetGetOrSetPropery.Invoke(target, sourceValue);
return true;
}
return false;
}
我编造了IGetProperty
和IGetOrSetProperty
。是否有可能在不使用反射的情况下以某种方式实现它们(以便检查它的编译时间)?
或者有一种优雅的方式来处理这种情况吗?
编辑:该示例具有误导性,因为目标不是使用Automapper,而是以某种方式将属性表示为对象。我意识到它实际上与使用属性作为&#34; ref&#34;例如,它更像是一个与语言相关的问题,一直在这里得到解答:Passing properties by reference in C#
答案 0 :(得分:3)
没有反射这是不可能的,但是表达式lambda给你编译时间检查:
public static bool Set<TTarget, TValue>(
this TTarget target,
Expression<Func<TTarget, TValue>> targetProperty,
TValue sourceValue)
{
var actualValue = targetProperty.Compile().Invoke(target);
if (actualValue.Equals(sourceValue))
{
return false;
}
var property = (PropertyInfo)((MemberExpression)targetProperty.Body).Member;
property.SetValue(target, sourceValue);
return true;
}
用法如下:
var hasChanged = target.Set(t => t.Name, source.Name);
工作示例:https://dotnetfiddle.net/CJVxIS
为什么你不应该这样做:
targetProperty.Compile()
很慢,答案 1 :(得分:0)
您可以考虑序列化/反序列化。效率可能较低(但同样,反射的基本实现也很昂贵)但它在语法上更具可读性和优雅性。另一个好处是,Json.Net非常灵活,因此您可以自定义复制行为(例如将Name属性映射到另一个名称的属性)
class MyDto
{
public string Name { get; set; }
public string Other { get; set; }
public string Remap { get; set; }
}
class MyBusinessObject
{
[JsonIgnore]
public string Other { get; set; }
public string Name { get; set; }
[JsonProperty(PropertyName = "Remap")]
public string RemmapedField { get; set; }
}
public T DeepCopy<T>(object o)
{
string json=JsonConvert.SerializeObject(o);
T newO=JsonConvert.DeserializeObject<T>(json);
return newO;
}
用法
MyDto source = new MyDto() { Name = "JP", Other = "Something",Remap="R" };
var target = DeepCopy<MyBusinessObject>(source);
结果:
姓名:&#34; JP&#34;
其他:null
RemmapedField:&#34; R&#34;