C#反射、克隆

Enr*_*uev 3 c# reflection clone

假设我有一个包含这个方法的类 Myclass:

 public class MyClass
    {
        public int MyProperty { get; set; }

        public int MySecondProperty { get; set; }

        public MyOtherClass subClass { get; set; }

        public object clone<T>(object original, T emptyObj)
        {

            FieldInfo[] fis = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);


            object tempMyClass = Activator.CreateInstance(typeof(T));


            foreach (FieldInfo fi in fis)
            {
                if (fi.FieldType.Namespace != original.GetType().Namespace)
                    fi.SetValue(tempMyClass, fi.GetValue(original));
                else
                    fi.SetValue(tempMyClass, this.clone(fi.GetValue(original), fi.GetValue(original)));
            }

            return tempMyClass;
        }
}
Run Code Online (Sandbox Code Playgroud)

然后这个类:

public class MyOtherClass 
{
    public int MyProperty777 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我这样做时:

MyClass a = new MyClass { 
                        MyProperty = 1, 
                        MySecondProperty = 2, 
                        subClass = new MyOtherClass() { MyProperty777 = -1 } 
                        };
            MyClass b = a.clone(a, a) as MyClass;
Run Code Online (Sandbox Code Playgroud)

如何在第二次调用 clone 时,T 是 object 类型而不是 MyOtherClass 类型

Dan*_*ker 5

您的第二个(递归)调用clone将 的结果GetValue作为第二个参数传递,该参数的类型为object,因此Tobject

IE

fi.SetValue(tempMyClass, this.clone(fi.GetValue(original), fi.GetValue(original)));
Run Code Online (Sandbox Code Playgroud)

GetValueon a的结果FieldInfo是 an object

鉴于您在所有情况下两次传递相同的内容,该clone方法的设计可能是错误的。您可能不需要那里的泛型。仅用于obj.GetType()获取第二个参数的类型信息(如果您确实需要第二个参数)。

使用泛型约束返回类型会更有意义,这样调用方就不需要强制转换。你也可以把 Clone 变成一个扩展方法,这样它就可以应用于任何东西。

另一方面,您尝试做的事情(自动深度克隆)不太可能普遍有用。大多数类最终都持有对它们不拥有的事物的引用,因此如果您克隆这样的对象,您最终会意外地克隆一半的应用程序框架。