复制属性 C#,但检查是否已设置属性

  • 本文关键字:属性 是否 设置 复制 c#
  • 更新时间 :
  • 英文 :


我自己努力开发JSON反序列化程序。只是为了训练。我快完成了,但我有一个复制问题。

我已经有了这个:

public void CopyValues<T>(T target, T source)
{
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(source, null);
if (value != null)
prop.SetValue(target, value, null);
}
}

主要问题就在这里。我有一个包含 2 个属性的属性。比如 content.link 和content.value。

如果我使用复制功能,它会正确复制。没有讨论。但是如果我将复制函数放入循环中,并且数据已填充,则源也具有 "内容",但没有链接和价值。

如果我再次复制,已经正确填充的属性将被覆盖,结果是我在 conent.link 和 content.value 处只有 null。

有没有办法检查链接和值是否设置为 null ?

为了复制嵌套属性,您需要使用递归函数:

public static void DeepCopy<T>(T target, T source)
{
DeepCloneImpl(typeof(T), source, target);
}
public static T DeepClone<T>(T template)
where T : new()
{
return (T)DeepCloneImpl(typeof(T), template);
}
private static object DeepCloneImpl(Type type, object template, object stump = null)
{
if (template == null)
{
return null;
}
var clone = stump ?? Activator.CreateInstance(type);
var clonableProperties = type.GetProperties()
.Where(x => x.GetMethod != null && x.SetMethod != null);
foreach (var property in clonableProperties)
{
var propertyType = property.PropertyType;
if (propertyType.GetTypeInfo().IsValueType || propertyType == typeof(string))
{
var value = property.GetValue(template);
property.SetValue(clone, value);
}
else if (propertyType.GetTypeInfo().IsClass && propertyType.GetConstructor(Type.EmptyTypes) != null)
{
var value = DeepCloneImpl(propertyType, property.GetValue(template));
property.SetValue(clone, value);
}
else if (propertyType.IsArray)
{
var source = property.GetValue(template) as Array;
if (source == null)
{
continue;
}
var elementType = propertyType.GetElementType();
if (elementType.GetTypeInfo().IsValueType || elementType == typeof(string))
{
var copies = Array.CreateInstance(elementType, source.Length);
Array.Copy(source, copies, source.Length);
property.SetValue(clone, copies);
}
else if (elementType.GetTypeInfo().IsClass)
{
var copies = Array.CreateInstance(elementType, source.Length);
for (int i = 0; i < source.Length; i++)
{
var copy = DeepCloneImpl(elementType, source.GetValue(i));
copies.SetValue(copy, i);
}
property.SetValue(clone, copies);
}
}
}
return clone;
}

这应该涵盖大多数用例,但是您必须处理自/循环引用。

据我所知,问题是值被覆盖了。从您的方法来看,它似乎正在做您所期望的事情,它是属性值的软克隆。根据您的情况中正确填充的属性,您必须进行比较以防止再次设置该属性。也许value != null实际上应该value == null,以便您仅在还没有值时才设置值。由于此方法的通用类型,如果这就是您使用!= null的原因,您不必担心属性不匹配。源和目标这两个参数的类型相同。

最新更新