有没有办法更新一个对象的所有属性,只改变它的值? [英] There is a way to update all properties of an object, changing only it values?

查看:38
本文介绍了有没有办法更新一个对象的所有属性,只改变它的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有这个对象,例如:

So, i have this object for exemple:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }

    public List<Car> Cars { get; set; }
    public List<User> Children { get; set; }
}

public class Car
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Color { get; set; }
}

那么,有没有办法更新User 对象,更新它ChildrenCars?如果对象中没有汽车来更新新对象中存在的汽车,则添加它,但是如果对象中存在要更新而新对象中没有,则将其从对象中移除以进行更新,并更新所有匹配的汽车的所有属性,以及 Children 属性.

So, there is a way to update a User object, updating it Children and Cars? If there isn't a car in the object to update that there is in the new object, add it, but if there is in the object to update and there isn't in the new object, remove it from the object to update, and update all attributes for all cars that are matched, and also to the Childrenproperty.

有可能吗?

推荐答案

是的!有可能,这里的解决方案(这个解决方案更新了所有属性,类属性和集合属性,但是如果里面有一个类,这个类需要继承一个AbstractEntity):

Yes! It's possible, here the solution (this solution update all properties, class properties and collection properties, but if there is an class inside, the class needs to inherit of an AbstractEntity):

private void UpdateAllProperties<idType, entityType>(entityType currentEntity, entityType newEntity)
    where idType : IEquatable<idType>
    where entityType : AbstractEntity<idType>
{
    var currentEntityProperties = currentEntity.GetType().GetProperties();
    var newEntityProperties = newEntity.GetType().GetProperties();

    foreach (var currentEntityProperty in currentEntityProperties)
    {
        foreach (var newEntityProperty in newEntityProperties)
        {
            if (newEntityProperty.Name == currentEntityProperty.Name)
            {
                if (currentEntityProperty.PropertyType.BaseType.IsGenericType &&
                    currentEntityProperty.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(AbstractEntity<>))
                {
                    var idPropertyType = currentEntityProperty.PropertyType.GetProperty("Id").PropertyType;
                    var entityPropertyType = currentEntityProperty.PropertyType;

                    this.InvokeUpdateAllProperties(currentEntityProperty.GetValue(currentEntity, null),
                                                    newEntityProperty.GetValue(newEntity, null),
                                                    idPropertyType, entityPropertyType);

                    break;
                }
                else if (currentEntityProperty.PropertyType.GetInterfaces().Any(
                            x => x.IsGenericType &&
                                    x.GetGenericTypeDefinition() == typeof(ICollection<>)))
                {
                    dynamic currentCollection = currentEntityProperty.GetValue(currentEntity, null);
                    dynamic newCollection = newEntityProperty.GetValue(newEntity, null);

                    this.UpdateCollectionItems(currentEntityProperty, currentCollection, newCollection);

                    dynamic itemsToRemove = Enumerable.ToList(Enumerable.Except(currentCollection, newCollection));
                    dynamic itemsToAdd = Enumerable.ToList(Enumerable.Except(newCollection, currentCollection));
                    dynamic itemsAreEqual = Enumerable.ToList(Enumerable.Intersect(currentCollection, newCollection));

                    for (int i = 0; i < itemsToRemove.Count; i++)
                    {
                        currentCollection.Remove(Enumerable.ElementAt(itemsToRemove, i));
                    }

                    for (int i = 0; i < itemsToAdd.Count; i++)
                    {
                        currentCollection.Add(Enumerable.ElementAt(itemsToAdd, i));
                    }

                    break;
                }
                else
                {
                    currentEntityProperty.SetValue(currentEntity, newEntityProperty.GetValue(newEntity, null), null);

                    break;
                }
            }
        }
    }
}

private void UpdateCollectionItems(PropertyInfo currentEntityProperty, dynamic currentCollection, dynamic newCollection)
{
    var collectionType = currentEntityProperty.PropertyType.GetInterfaces().Where(
                            x => x.IsGenericType &&
                                    x.GetGenericTypeDefinition() == typeof(ICollection<>)).First();

    var argumentType = collectionType.GetGenericArguments()[0];

    if (argumentType.BaseType.IsGenericType &&
        argumentType.BaseType.GetGenericTypeDefinition() == typeof(AbstractEntity<>))
    {
        foreach (var currentItem in currentCollection)
        {
            foreach (var newItem in newCollection)
            {
                if (currentItem.Equals(newItem))
                {
                    var idPropertyType = currentItem.GetType().GetProperty("Id").PropertyType;
                    var entityPropertyType = currentItem.GetType();

                    this.InvokeUpdateAllProperties(currentItem, newItem, idPropertyType, entityPropertyType);
                }
            }
        }
    }
}

private void InvokeUpdateAllProperties(dynamic currentEntity, dynamic newEntity, dynamic idPropertyType, dynamic entityPropertyType)
{
    var method = this.GetType().GetMethod("UpdateAllProperties", BindingFlags.Instance | BindingFlags.NonPublic);
    var genericMethod = method.MakeGenericMethod(idPropertyType, entityPropertyType);
    genericMethod.Invoke(this, new[] { currentEntity, newEntity });
}

用法示例:

抽象实体:

public abstract class AbstractEntity<idType>
    where idType : IEquatable<idType>
{
    public idType Id { get; set; }
}

示例类:

public class User : AbstractEntity<int>
{
    public string Name { get; set; }
    public List<Car> OtherCars { get; set; }
    public Car MainCar { get; set; }

    public bool Equals(Car other)
    {
        if (this.Id == other.Id)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

public class Car : AbstractEntity<int>
{
    public string Name { get; set; }
    public string Color { get; set; }

    public bool Equals(Car other)
    {
        if (this.Id == other.Id)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

使用方法:

User currentUser = new User()
{
    Id = 1,
    Name = "Vinicius",
    OtherCars = new List<Car>()
    {
        new Car()
        {
            Id = 2,
            Name = "Corsa II",
            Color = "Azul"
        },
        new Car()
        {
            Id = 3,
            Name = "Palio",
            Color = "Vermelho"
        },
        new Car()
        {
            Id = 4,
            Name = "Fusca",
            Color = "Azul"
        }
    },
    MainCar = new Car()
    {
        Id = 1,
        Name = "Corsa",
        Color = "Preto"
    }
};

User updatedUser = new User()
{
    Id = 1,
    Name = "Vinicius Ottoni",
    OtherCars = new List<Car>()
    {
        new Car()
        {
            Id = 5,
            Name = "Voyage",
            Color = "Azul"
        },
        new Car()
        {
            Id = 6,
            Name = "Voyage II",
            Color = "Vermelho"
        },
        new Car()
        {
            Id = 4,
            Name = "Fusca",
            Color = "Rosa"
        }
    },
    MainCar = new Car()
    {
        Id = 2,
        Name = "Voyage",
        Color = "Vinho"
    }
};

this.UpdateAllProperties<int, User>(currentUser, updatedUser);

这篇关于有没有办法更新一个对象的所有属性,只改变它的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆