首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET反射-检查2个类作为彼此的成员添加。

.NET反射-检查2个类作为彼此的成员添加。
EN

Stack Overflow用户
提问于 2017-11-08 13:29:15
回答 3查看 127关注 0票数 0

如何检查两个类是否添加为彼此的成员。

代码语言:javascript
复制
class Team
{
   Driver driver{ get; set;}
   Driver codriver{ get; set;}
}

class Driver
{
   Team parentTeam{ get; set;}
}

我用下列方法取得物业:-

代码语言:javascript
复制
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo property in properties)
{
   ////if (!isParent) //need to find this.
   //{
   object propertyValue = property.GetValue(obj);
   if (propertyValue != null)
   {
      // Get the deep clone of the field in the original object and assign the clone to the field in the new object.
      property.SetValue(copiedObject, CloneProcedure(propertyValue));
   }
   //}
}

我想跳过第一个类,它是第二个属性,当迭代第二个类时。注意:你们中的一些人可能觉得我的类被错误地声明了,但是这是一个遗留的系统,我没有机会重组这些类。

我尝试过DeclaringType,得到了property.DeclaringType,但是obj.GetType().DeclaringType是空的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-08 14:04:56

从外观上看,您是深度克隆,实际上您不希望跳过父类型,只是不希望同一个实例生成多个克隆。

您可以做的是保留一个保存以前克隆实例的引用的Dictionary<object, object>

代码语言:javascript
复制
object CloneProcedure(object o, Dictionary<object, object> cloned)
{
    object clone;
    if (cloned.TryGetValue(o, out clone))
    {
        // this object has been cloned earlier, return reference to that clone
        return clone;
    }

    clone = Activator.CreateInstance(o.GetType());
    cloned[o] = clone;

    PropertyInfo[] properties = ...
    foreach ...
    {
        ...
        property.SetValue(copiedObject, CloneProcedure(propertyValue, cloned));
    }
}

这确保没有任何对象被多次克隆,如果多个属性指向同一个实例,克隆也将指向同一个克隆实例。

票数 1
EN

Stack Overflow用户

发布于 2017-11-08 13:56:59

尝尝这个

代码语言:javascript
复制
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo property in properties)
{
   if (property.PropertyType == typeof(Parent)) 
   {
       object propertyValue = property.GetValue(obj);
       if (propertyValue != null)
       {
          // Get the deep clone of the field in the original object and assign the clone to the field in the new object.
          property.SetValue(copiedObject, CloneProcedure(propertyValue));
       }
   }
}

如果要允许继承,可以使用Type.IsAssignableFrom

票数 0
EN

Stack Overflow用户

发布于 2017-11-17 13:37:18

如果这对任何人都有好处的话,我将发布我最后的深拷贝实用程序

代码语言:javascript
复制
 public static class DeepCloneHelper
{
    private static string[] _excludedPropertyNames = null;

    /// <summary>
    /// Get the deep clone of an object.
    /// </summary>
    /// <typeparam name="T">The type of the source.</typeparam>
    /// <param name="source">It is the object used to deep clone.</param>
    /// <param name="propertyNames"></param>
    /// <returns>Return the deep clone.</returns>
    public static T DeepClone<T>(T source, string[] propertyNames = null)
    {
        if (source == null)
        {
            throw new ArgumentNullException("Object is null");
        }
        if (propertyNames != null) { _excludedPropertyNames = propertyNames; }
        return (T)CloneProcedure(source, new Dictionary<object, object>());
        // return target;
    }

    /// <summary>
    /// The method implements deep clone using reflection.
    /// </summary>
    /// <param name="source">It is the object used to deep clone.</param>
    /// <param name="cloned"></param>
    /// <returns>Return the deep clone.</returns>
    private static object CloneProcedure(Object source, Dictionary<object, object> cloned)
    {
        if (source == null)
        {
            return null;
        }

        object clone;
        if (cloned.TryGetValue(source, out clone))
        {
            // this object has been cloned earlier, return reference to that clone
            return clone;
        }

        Type type = source.GetType();

        // If the type of object is the value type, we will always get a new object when 
        // the original object is assigned to another variable. So if the type of the 
        // object is primitive or enum, we just return the object. We will process the 
        // struct type subsequently because the struct type may contain the reference 
        // fields.
        // If the string variables contain the same chars, they always refer to the same 
        // string in the heap. So if the type of the object is string, we also return the 
        // object.
        if (type.IsPrimitive || type.IsEnum || type == typeof(string))
        {
            return source;
        }
        // If the type of the object is the Array, we use the CreateInstance method to get
        // a new instance of the array. We also process recursively this method in the 
        // elements of the original array because the type of the element may be the reference 
        // type.
        else if (type.IsArray)
        {
            Type typeElement = Type.GetType(type.FullName.Replace("[]", string.Empty) + "," + type.Assembly.FullName);
            var array = source as Array;
            Array copiedArray = Array.CreateInstance(typeElement, array.Length);
            cloned[source] = copiedArray;

            for (int i = 0; i < array.Length; i++)
            {
                // Get the deep clone of the element in the original array and assign the 
                // clone to the new array.
                copiedArray.SetValue(CloneProcedure(array.GetValue(i), cloned), i);

            }
            return copiedArray;
        }

        else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
        {
            if (typeof(IList).IsAssignableFrom(type))
            {
                var collection = (IList)Activator.CreateInstance(type);
                cloned[source] = collection;

                foreach (var element in source as IEnumerable)
                {
                    collection.Add(CloneProcedure(element, cloned));
                }
                return collection;
            }
            else if (type.IsGenericType)
            {
                var objectType = type.GetGenericArguments().Single();
                if (typeof(IList<>).MakeGenericType(objectType).IsAssignableFrom(type) ||
                    typeof(ISet<>).MakeGenericType(objectType).IsAssignableFrom(type))
                {
                    var collection = Activator.CreateInstance(type);
                    cloned[source] = collection;

                    var addMethod = collection.GetType().GetMethod("Add");
                    foreach (var element in source as IEnumerable)
                    {
                        addMethod.Invoke(collection, new[] { CloneProcedure(element, cloned) });
                    }
                    return collection;
                }
            }
            return source;
        }
        // If the type of the object is class or struct, it may contain the reference fields, 
        // so we use reflection and process recursively this method in the fields of the object 
        // to get the deep clone of the object. 
        // We use Type.IsValueType method here because there is no way to indicate directly whether 
        // the Type is a struct type.
        else if (type.IsClass || type.IsValueType)
        {
            object copiedObject = Activator.CreateInstance(source.GetType());
            cloned[source] = copiedObject;

            // Get all PropertyInfo.
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                if (_excludedPropertyNames == null || !_excludedPropertyNames.Contains(property.Name))
                {
                    object propertyValue = property.GetValue(source);
                    if (propertyValue != null && property.CanWrite && property.GetSetMethod() != null)
                    {
                        // Get the deep clone of the field in the original object and assign the 
                        // clone to the field in the new object.
                        property.SetValue(copiedObject, CloneProcedure(propertyValue, cloned));
                    }
                }
            }
            return copiedObject;
        }
        else
        {
            throw new ArgumentException("The object is unknown type");
        }
    }
}

参考资料:https://code.msdn.microsoft.com/windowsdesktop/CSDeepCloneObject-8a53311e

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47181007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档