复制具有不同命名空间的两个相同对象(递归reflection)
我在c#中工作,有几个工作区有一个特定的类,在每个工作区中它总是相同的。 我希望能够拥有此类的副本,以便能够在不处理命名空间差异的情况下使用它。 例子:
namespace1 { class class1{ public class2; } class class2{ public string; } } namespace2 { class class1{ public class2; } class class2{ public string; } }
在我复制的类中,我有一个函数将所有数据复制到命名空间的类之一。 如果我只有c#标准类型,它会工作。 一旦我处理class2对象(也来自不同的命名空间),我得到了exeption(“对象与目标类型不匹配。”)
public Object toNamespaceClass(Object namespaceClass) { try { Type fromType = this.GetType(); Type toType = namespaceClass.GetType(); PropertyInfo[] fromProps = fromType.GetProperties(); PropertyInfo[] toProps = toType.GetProperties(); for (int i = 0; i < fromProps.Length; i++) { PropertyInfo fromProp = fromProps[i]; PropertyInfo toProp = toType.GetProperty(fromProp.Name); if (toProp != null) { toProp.SetValue(this, fromProp.GetValue(namespaceClass, null), null); } } } catch (Exception ex) { } return namespaceClass; }
任何人都知道如何处理这种“递归reflection”。
我希望eveything是可以理解的。
谢谢再见!
编辑:我想我已经解决了(至少在我的脑海里),我明天会在工作中尝试解决方案。 如果属性不是标准类型,可以将我的函数从我的类中取出并递归使用它可能是解决方案。
我有类似的问题。 我必须使用类似的类,但仅在命名空间方面有所不同。 作为一种快速解决方案,我在下面的步骤中执
- 将源类序列化为XML。
- 在SerializedXML中,将源命名空间替换为目标命名空间。
- 使用目标类型进行DeSerialize。
我知道上面的方法有性能开销,但它实现快速且无错误。
BinaryFormatter在.Net 4.5中不起作用,因为它记住了实例创建的类的类型。 但是对于JSON格式,它没有。 JSON序列化程序由Microsoft在DataContractJosnSerializer中实现。
这有效:
public static T2 DeepClone(T1 obj) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T1)); DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T2)); using (var ms = new MemoryStream()) { serializer.WriteObject(ms, obj); ms.Position = 0; return (T2)deserializer.ReadObject(ms); } }
用法如下:
var b = DeepClone(a);
我解决了它,只是为了让你知道我是怎么做到的:这个解决方案很完美,因为它只处理1维数组而不是更多。
public static Object CopyObject(Object from , Object to) { try { Type fromType = from.GetType(); Type toType = to.GetType(); PropertyInfo[] fromProps = fromType.GetProperties(); PropertyInfo[] toProps = toType.GetProperties(); for (int i = 0; i < fromProps.Length; i++) { PropertyInfo fromProp = fromProps[i]; PropertyInfo toProp = toType.GetProperty(fromProp.Name); if (toProp != null) { if (toProp.PropertyType.Module.ScopeName != "CommonLanguageRuntimeLibrary") { if (!toProp.PropertyType.IsArray) { ConstructorInfo ci = toProp.PropertyType.GetConstructor(new Type[0]); if (ci != null) { toProp.SetValue(to, ci.Invoke(null), null); toProp.SetValue(to, gestionRefelexion.CopyObject(fromProp.GetValue(from, null), toProp.GetValue(to, null)), null); } } else { Type typeToArray = toProp.PropertyType.GetElementType(); Array fromArray = fromProp.GetValue(from, null) as Array; toProp.SetValue(to, copyArray(fromArray, typeToArray), null); } } else { toProp.SetValue(to, fromProp.GetValue(from, null), null); } } } } catch (Exception ex) { } return to; } public static Array copyArray(Array from, Type toType) { Array toArray =null; if (from != null) { toArray= Array.CreateInstance(toType, from.Length); for (int i = 0; i < from.Length; i++) { ConstructorInfo ci = toType.GetConstructor(new Type[0]); if (ci != null) { toArray.SetValue(ci.Invoke(null), i); toArray.SetValue(gestionRefelexion.CopyObject(from.GetValue(i), toArray.GetValue(i)), i); } } } return toArray; }
希望这可以帮助一些人。 谢谢你们帮助大家。 干杯
public static T DeepClone(T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T) formatter.Deserialize(ms); } }
从这里
来自不同命名空间的两个相同或相似的对象?
你有这个:
namespace Cars { public class car { public string Name; public void Start() { ... } } } namespace Planes { public class plane { public string Name; public void Fly() { ... } } }
是时候应用一些类inheritance了:
namespace Vehicles { public class vehicle { public string Name; } // class } // namespace using Vehicles; namespace Cars { public class car: vehicle { public string Name; public void Start() { ... } } // class } // namespace using Vehicles; namespace Planes { public class plane: vehicle { public void Fly() { ... } } }
要复制,有一个复制方法或构造函数,但是,我更喜欢自定义的:
namespace Vehicles { public class vehicle { public string Name; public virtual CopyFrom (vehicle Source) { this.Name = Source.Name; // other fields } } // class } // namespace
干杯。
您需要将所有重复的类重构为单个共享类,或者实现所有各个类实现的公共接口。 如果您确实无法修改基础类型,请为实现公共接口的每个类创建一个子类。
是的,你可以用reflection做到这一点……但是你真的不应该这样做,因为你最终会遇到脆弱,容易出错的代码。
使用协议缓冲区可以优雅地解决此问题,因为协议缓冲区不包含有关它们序列化类型的任何元数据。 具有相同字段和属性的两个类序列化为完全相同的位。
这是一个小function,将从原始类型更改为C副本类型
static public C DeepCopyChangingNamespace(O original) { using (MemoryStream ms = new MemoryStream()) { Serializer.Serialize(ms, original); ms.Position = 0; C c = Serializer.Deserialize(ms); return c; } }
用法是
namespace1.class1 orig = new namespace1.class1(); namespace2.class1 copy = DeepCopyChangingNamespace(orig);