我在c#中工作,有几个工作区有一个特定的类,在每个工作区中它总是相同的。 我希望能够拥有此类的副本,以便能够使用它而无需处理命名空间差异。 例如:
namespace1 {
class class1{
public class2;
}
class class2{
public string;
}
}
namespace2 {
class class1{
public class2;
}
class class2{
public string;
}
}
在我复制的Class中,我有一个函数将所有数据复制到命名空间的类之一。 如果我只有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;
}
任何人都知道如何处理这种“递归反射”。
我希望eveything是可以理解的。
谢谢,再见!
编辑: 我想我已经解决了问题(至少在我看来),明天我会尝试解决这个问题。如果属性不是标准类型,可以将我的函数从我的类中取出并递归使用它可能是解决方案。
答案 0 :(得分:6)
BinaryFormatter在.Net 4.5中不起作用,因为它记得实例创建的类的类型。但是对于JSON格式,它没有。 JSON序列化程序由Microsoft在DataContractJosnSerializer中实现。
这有效:
public static T2 DeepClone<T1, T2>(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, B>(a);
答案 1 :(得分:5)
我遇到了类似的问题。我必须使用类似的类,但仅在命名空间方面有所不同。作为一种快速解决方案,我在下面的步骤中执行了它。
我知道上面的方法存在性能开销,但实现起来很快且没有错误。
答案 2 :(得分:2)
我解决了,只是为了让你知道我是怎么做到的: 这个解决方案非常完美,因为它只能处理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;
}
希望这可以帮助一些人。 谢谢你们帮助大家。 干杯
答案 3 :(得分:0)
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
来自here
答案 4 :(得分:0)
来自不同命名空间的两个相同或相似的对象?
你有这个:
namespace Cars
{
public class car {
public string Name;
public void Start() { ... }
}
}
namespace Planes
{
public class plane {
public string Name;
public void Fly() { ... }
}
}
应用某些类继承的时间:
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
干杯。
答案 5 :(得分:0)
您需要将所有重复的类重构为单个共享类,或者实现所有各个类实现的公共接口。如果你真的无法修改底层类型,请为每个实现公共接口的类创建一个子类。
是的,你可以用反射做到这一点......但是你真的不应该这样做,因为你最终会遇到脆弱,容易出错的代码。
答案 6 :(得分:0)
使用Protocol Buffers可以优雅地解决此问题,因为协议缓冲区不包含有关它们序列化类型的任何元数据。两个相同领域和类别的班级属性序列化为精确相同的位。
这是一个小功能,将从 O 原始类型更改为 C 复制类型
static public C DeepCopyChangingNamespace<O,C>(O original)
{
using (MemoryStream ms = new MemoryStream())
{
Serializer.Serialize(ms, original);
ms.Position = 0;
C c = Serializer.Deserialize<C>(ms);
return c;
}
}
用法是
namespace1.class1 orig = new namespace1.class1();
namespace2.class1 copy =
DeepCopyChangingNamespace<namespace1.class1, namespace2.class1>(orig);