我有以下代码,它通过匹配属性名称将属性值从一个对象复制到另一个对象:
public static void CopyProperties(object source, object target,bool caseSenstive=true)
{
PropertyInfo[] targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo tp in targetProperties)
{
var sourceProperty = sourceProperties.FirstOrDefault(p => p.Name == tp.Name);
if (sourceProperty == null && !caseSenstive)
{
sourceProperty = sourceProperties.FirstOrDefault(p => p.Name.ToUpper() == tp.Name.ToUpper());
}
// If source doesn't have this property, go for next one.
if(sourceProperty ==null)
{
continue;
}
// If target property is not writable then we can not set it;
// If source property is not readable then cannot check it's value
if (!tp.CanWrite || !sourceProperty.CanRead)
{
continue;
}
MethodInfo mget = sourceProperty.GetGetMethod(false);
MethodInfo mset = tp.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null)
{
continue;
}
if (mset == null)
{
continue;
}
var sourcevalue = sourceProperty.GetValue(source, null);
tp.SetValue(target, sourcevalue, null);
}
}
当目标和源上的属性类型相同时,这种方法很有效。但是当需要进行强制转换时,代码不起作用。
例如,我有以下对象:
class MyDateTime
{
public static implicit operator DateTime?(MyDateTime myDateTime)
{
return myDateTime.DateTime;
}
public static implicit operator DateTime(MyDateTime myDateTime)
{
if (myDateTime.DateTime.HasValue)
{
return myDateTime.DateTime.Value;
}
else
{
return System.DateTime.MinValue;
}
}
public static implicit operator MyDateTime(DateTime? dateTime)
{
return FromDateTime(dateTime);
}
public static implicit operator MyDateTime(DateTime dateTime)
{
return FromDateTime(dateTime);
}
}
如果我执行以下操作,则会调用隐式强制转换并且一切正常:
MyDateTime x= DateTime.Now;
但是当我有一个两个对象,其中一个有DateTime而另一个有MyDateTime,我使用上面的代码将属性从一个对象复制到另一个对象时,它没有并生成一个错误,说明DateTime无法转换为MyTimeDate。
如何解决此问题?
答案 0 :(得分:1)
应该工作的一个可怕方法是混合dynamic
和反思:
private static T ConvertValue<T>(dynamic value)
{
return value; // This will perform conversion automatically
}
然后:
var sourceValue = sourceProperty.GetValue(source, null);
if (sourceProperty.PropertyType != tp.PropertyType)
{
var method = typeof(PropertyCopier).GetMethod("ConvertValue",
BindingFlags.Static | BindingFlags.NonPublic);
method = method.MakeGenericMethod(new[] { tp.PropertyType };
sourceValue = method.Invoke(null, new[] { sourceValue });
}
tp.SetValue(target, sourceValue, null);
我们需要使用反射来使用正确的类型参数调用泛型方法,但动态类型将为您使用正确的转换运算符。
哦,最后一个请求:请不要在我的代码附近包含我的名字 ,无论是在评论,提交日志中。 AARGH。