我在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;
}
任何人都知道如何处理这种"递归反射"。
我希望一切都可以理解。
谢谢,再见!
编辑:我想我已经解决了(至少在我的脑海中(,我明天会在工作中尝试这个解决方案。如果一个属性不是标准类型,那么将我的函数从类中取出并递归使用它可能是解决方案。
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);
我也遇到了类似的问题。我使用了类似的类,但仅在名称空间方面有所不同。作为一个快速的解决方案,我执行了以下步骤,它是有效的。
- 将源类序列化为XML
- 在SerializedXML中,将源命名空间替换为目标命名空间
- 使用目标类型取消序列化
我知道上面的方法会带来性能开销,但实现起来很快而且没有错误。
我解决了它,只是想让你知道我是如何做到的:这个解决方案非常完美,因为它只处理一维数组,而不是更多。
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>(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() { ... }
}
}
是时候应用一些类继承了:
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
干杯。
您要么需要将所有重复的类重构为一个共享类,要么实现所有不同类都实现的公共接口。如果您真的不能修改底层类型,请为每个实现公共接口的类型创建一个子类。
是的,你可以通过反思来做到。。。但你真的不应该这样做,因为你最终会得到脆弱、容易出错的代码。
使用协议缓冲区可以很好地解决这个问题,因为协议缓冲区不包含任何关于它们序列化的类型的元数据。具有相同字段的两个类&属性序列化为完全相同的位。
这里有一个小函数,它将从原始类型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);