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

时间:2018-10-10 14:35:28

标签: 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?

2 个答案:

答案 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,则不必担心属性不匹配。源和目标这两个参数的类型相同。