我自己研究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?
答案 0 :(得分:1)
要复制嵌套的属性,您将需要使用递归函数:
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;
}
这应该涵盖了大多数用例,但是您将不得不处理自/循环引用。
答案 1 :(得分:0)
据我所知,问题在于值已被覆盖。从您的方法来看,它似乎正在按照您的期望进行操作,它是属性值的一个软克隆。根据情况正确填充的属性,您必须进行比较以防止再次设置该属性。也许value != null
实际上应该是value == null
,这样您才可以在尚不存在的情况下设置该值。由于此方法具有通用类型,因此如果您使用!= null
,则不必担心属性不匹配。源和目标这两个参数的类型相同。