Serializing didn't show value - c#

EDIT: My attempt to create a simple sample was a failure. I thought I had replicated the issue with my real code, but it was really just a value not set to public, so my serialization was failing.
Original Post:
I have a class with a value to be set on it (A below.) Another class has an A in it and a setter for A's value (B below.) I have a bunch of B's in a list and a series of foreach's and casts. On the inside of it all, I call the setter, but the result of all of this is a list where the setter appears to have never been called. What's going wrong here and how do I get the new value to take?
I was able to recreate the problem in a more simple set of code.
Here's a fiddle: https://dotnetfiddle.net/B4YVHU
Alternatively, here's the code:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace ConsoleApplication28
{
class A
{
public string value = null;
}
class B
{
private A a = new A();
public void SetAValue(string s)
{
Console.WriteLine($"Value is set to: {s}");
a.value = s;
}
}
public class Program
{
public static void Main(string[] args)
{
object list = new List<B> { new B(), new B() };
if ( list is IEnumerable<object> enumerable)
{
foreach (var value in enumerable)
{
if (value is B a)
{
a.SetAValue("blooop");
}
}
}
Console.WriteLine(Serialization.SerializeJson(list));
}
}
// You can ignore this. It's just to more easily display the object result
class Serialization
{
private static JsonSerializer _serializer;
static Serialization()
{
_serializer = new JsonSerializer();
}
public static string SerializeJson<T>( T value )
{
string jsonString;
using ( var stringWriter = new StringWriter() )
using ( var writer = new JsonTextWriter( stringWriter ) )
{
_serializer.Serialize(writer, value);
jsonString = stringWriter.ToString();
}
return jsonString;
}
}
}

in Class B:
public A a {get; set;} = new A();
In order to serialize, variables must be public.
https://dotnetfiddle.net/B4YVHU

Related

ReferenceEquals with casting challenge. Casting to child type make ReferenceEquals return false

Casting does not make copies of objects. More concretely IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle, reference equals is false if I change the log at the end from the Cast<BaseClass> to Cast<DerivedClass1>. Check logs at the main program.
are equal: True areEqualRef: True areEqualRef: False
Posting the code, just in case, omit it of you get my point playing around with the fiddle :)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp17
{
public class BaseClass {
string name = "I am base";
public Type type;
public enum Type {
a,b,c,d
}
public BaseClass(Type type) {
this.type = type;
}
}
public class DerivedClass1 : BaseClass
{
string name = "I am derivedA";
public DerivedClass1(): base(Type.a) {
}
}
public class DerivedClass2 : BaseClass
{
string name = "I am derivedB";
public DerivedClass2() : base(Type.b)
{
}
}
public class Foo
{
public Dictionary<BaseClass.Type, List<BaseClass>> dict = new Dictionary<BaseClass.Type, List<BaseClass>>();
public Foo() {
dict[BaseClass.Type.a] = new List<BaseClass>();
dict[BaseClass.Type.b] = new List<BaseClass>();
dict[BaseClass.Type.c] = new List<BaseClass>();
dict[BaseClass.Type.d] = new List<BaseClass>();
AddItem(new DerivedClass1());
AddItem(new DerivedClass1());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
}
public IEnumerable<T> GetEnumByType<T>(BaseClass.Type type) where T : BaseClass
{
if (dict.ContainsKey(type))
{
if (type == BaseClass.Type.a)
{
Console.WriteLine($"are equal: { object.ReferenceEquals(dict[type].Cast<T>(), dict[BaseClass.Type.a])}");
}
return dict[type].Cast<T>();
}
return null;
}
public void AddItem<T>(T item) where T : BaseClass
{
dict[item.type].Add(item);
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
IEnumerable myList = foo.GetEnumByType<BaseClass>(BaseClass.Type.a);
Console.WriteLine($"areEqualRef: {object.ReferenceEquals(foo.dict[BaseClass.Type.a].Cast<BaseClass>(), foo.dict[BaseClass.Type.a])}");
Console.ReadLine();
}
}
}
Update:
Updated the fiddle with both logs to avoid the need of copy/pasting
You need to notionally separate what is being compared here. When it says that Enumerable.Cast<T> doesn't make copies of objects, it is talking about the individual objects in the sequence. Not the sequence itself. In order to perform the necessary reshaping, the sequence returned from the Cast<T> method is a different wrapper/decorator instance over the original sequence.
Since you're using ReferenceEquals on the sequence, this will report false. However, if you were to compare each object from the sequences (pairwise in turn), you would find that those were the same objects.

C# binary search tree

I was making a test case for some code on binary search tree my professor gave
public static void Main(string [] args)
{
//on my prof's code, public class BinSearchTree<T>
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
myTree.Insert(5);
myTree.Insert(2);
myTree.Insert(1);
Console.WriteLine(myTree.ToString());
Console.ReadKey();
}
It compiles, but it displays
BinSearchTree`1[System.Int32]
Can somebody tell me why it displays that?
my prof's code:
public class BinSearchTree<T> where T : IComparable<T>
{
private class OurTreeNode<T>
{
public T Data { get; set; }
public OurTreeNode<T> Left;
public OurTreeNode<T> Right;
public OurTreeNode(T d = default(T), OurTreeNode<T> leftnode = null, OurTreeNode<T> rightnode = null)
{
Data = d;
Left = leftnode;
Right = rightnode;
}
public override string ToString()
{
return Data.ToString();
}
}
//...other methods
//prof's Insert method
public void Insert(T newItem)
{
mRoot = Insert(newItem, mRoot);
}
private OurTreeNode<T> Insert(T newItem, OurTreeNode<T> pTmp)
{
if (pTmp == null)
return new OurTreeNode<T>(newItem, null, null);
else if (newItem.CompareTo(pTmp.Data) < 0)
pTmp.Left = Insert(newItem, pTmp.Left);
else if (newItem.CompareTo(pTmp.Data) > 0)
pTmp.Right = Insert(newItem, pTmp.Right);
else
throw new ApplicationException("...");
return pTmp;
}
}
I tried adding a ToString() method after the Insert method but it gives me an error when I used foreach. Is there a way of displaying it without making too much extra methods?
The class is using the default (Object's) ToString() implementation. You have 2 options:
walk though the elements of the tree and print it yourself
ask the author to implement/override the ToString() method
Can somebody tell me why it displays that?
It displays that because ToString() prints the type definition.
Default implementations of the Object.ToString method return the fully qualified name of the object's type. (from the docs)
For instance, the following short program prints System.Collections.Generic.List`1[System.Int32], which is the type of List<int>.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
List<int> myTree = new List<int>();
myTree.Add(10);
Console.WriteLine(myTree.ToString());
}
}
Here are the rudiments of how to override the ToString() method to produce some meaningful output.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
Console.WriteLine(myTree.ToString());
}
}
public class BinSearchTree<T> where T : IComparable<T>
{
private List<T> values = new List<T>();
// rest of class omitted for clarity
public void Insert(T val) {
values.Add(val);
}
public override string ToString() {
var result = string.Empty;
foreach(var v in values)
{
result += v + ", ";
}
return result;
}
}
Output
10, 15,
As you have created the object of BinaryTree Class and have not overridden the ToString() method inside BinaryTree Class. You have not created object of OurTreeNode class and not calling ToString() method overriden inside it. Hence it is giving you the default ToString() method output of BinaryTree Class.
BinSearchTree<int> myTree = new BinSearchTree<int>();
You are calling
Console.WriteLine(myTree.ToString());

DataContractJsonSerializer ; ISerializable GetObjectData called with .NET but not with mono

Below is a simplified example of what I'm trying to accomplish.
I have a class DoNotSerializeMe which is part of an external library and cannot be serialized.
using System;
namespace CustomJsonSerialization
{
public class DoNotSerializeMe
{
public string WhyAmIHere;
public DoNotSerializeMe(string mystring)
{
Console.WriteLine(" In DoNotSerializeMe constructor.");
WhyAmIHere = "( constructed with " + mystring + " )";
}
}
}
I also have a class SerializeMe which has a member of type DoNotSerializeMe. I can make this class implement ISerializable and get around the issue of DoNotSerializeMe not being serializable by pulling data and calling the constructor.
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace CustomJsonSerialization
{
[System.Serializable]
public class SerializeMe : ISerializable
{
public DoNotSerializeMe SerializeMeThroughISerializable;
public SerializeMe(string mystring)
{
SerializeMeThroughISerializable = new DoNotSerializeMe(mystring);
}
protected SerializeMe(SerializationInfo info, StreamingContext context)
{
System.Console.WriteLine(" In SerializeMe constructor (ISerializable)");
SerializeMeThroughISerializable = new DoNotSerializeMe(info.GetString("SerializeMeThroughISerializable"));
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
System.Console.WriteLine(" In SerializeMe.GetObjectData()");
info.AddValue("SerializeMeThroughISerializable",
"( deserialized through getObjectData " +
SerializeMeThroughISerializable.WhyAmIHere + " )");
}
}
}
Below is a short program that serializes and deserializes the object:
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace CustomJsonSerialization
{
public class Program
{
public static void Main(string[] args)
{
SerializeMe serializeme = new SerializeMe("initial");
Console.WriteLine("I created it: {0}", serializeme.SerializeMeThroughISerializable.WhyAmIHere);
Console.WriteLine();
MemoryStream memstream = new MemoryStream();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(SerializeMe));
serializer.WriteObject(memstream, serializeme);
Console.WriteLine("I serialized it: {0}", serializeme.SerializeMeThroughISerializable.WhyAmIHere);
Console.WriteLine();
Console.WriteLine("Json:");
Console.WriteLine(Encoding.ASCII.GetString(memstream.ToArray()));
Console.WriteLine();
memstream.Seek(0, SeekOrigin.Begin);
SerializeMe anotherSerializeMe = (SerializeMe)serializer.ReadObject(memstream);
Console.WriteLine("I deserialized it: {0}", anotherSerializeMe.SerializeMeThroughISerializable.WhyAmIHere);
}
}
}
When running through .NET (4.5), I get the following:
In DoNotSerializeMe constructor.
I created it: ( constructed with initial )
In SerializeMe.GetObjectData()
I serialized it: ( constructed with initial )
Json:
{"SerializeMeThroughISerializable":"( deserialized through getObjectData ( constructed with initial ) )"}
In SerializeMe constructor (ISerializable)
In DoNotSerializeMe constructor.
I deserialized it: ( constructed with ( deserialized through getObjectData ( constructed with initial ) ) )
The serializer called the ISerializable construction and the GetObjectData when serializing / deserializing (as expected). I never serialize or deserialize the DoNotSerializeMe object directly.
However, when running the same build through mono (tried 3.10.0 and 4.0.2), I get the following:
In DoNotSerializeMe constructor.
I created it: ( constructed with initial )
I serialized it: ( constructed with initial )
Json:
{"SerializeMeThroughISerializable":{"WhyAmIHere":"( constructed with initial )"}}
I deserialized it: ( constructed with initial )
Obviously, if DoNotSerializeMe was truly not serializable, this would lead to an error.
Is there an elegant way to get around this without using Json.NET? I'm not sure why mono isn't behaving the same way as .NET.
I'm going to suggest an alternative approach: use a surrogate data transfer type to serialize your DoNotSerializeMe class. One way to do this is with Data Contract Surrogates. But are data contract surrogates supported on mono? The current version of the source code shows that they are, but this version shows it as [MonoTODO], so I cannot guarantee that your version of mono has a working implementation for DataContractJsonSerializer.DataContractSurrogate.
However, a manual surrogate property will always work. For instance, the following SerializeMe type can be serialized and serialized even though its DoNotSerializeMe member cannot be serialized directly:
public class DoNotSerializeMe
{
public readonly string WhyAmIHere;
readonly bool ProperlyConstructed; // data contract serializer does not call the constructor
public DoNotSerializeMe(string mystring)
{
Console.WriteLine(string.Format(" In DoNotSerializeMe constructor, mystring = \"{0}\"", mystring));
WhyAmIHere = mystring;
ProperlyConstructed = true;
}
public void Validate()
{
if (!ProperlyConstructed)
throw new InvalidOperationException("!ProperlyConstructed");
}
}
public class SerializeMe
{
[IgnoreDataMember]
public DoNotSerializeMe CannotBeSerializedDirectly;
public DoNotSerializeMeSurrogate DoNotSerializeMeSurrogate
{
get
{
if (CannotBeSerializedDirectly == null)
return null;
return new DoNotSerializeMeSurrogate { WhyAmIHereSurrogate = CannotBeSerializedDirectly.WhyAmIHere };
}
set
{
if (value == null)
CannotBeSerializedDirectly = null;
else
CannotBeSerializedDirectly = new DoNotSerializeMe(value.WhyAmIHereSurrogate);
}
}
public string SomeOtherField { get; set; }
}
public class DoNotSerializeMeSurrogate
{
public string WhyAmIHereSurrogate { get; set; }
}
Using this approach looks simpler than implementing ISerializable since all the members other than CannotBeSerializedDirectly continue to be serialized automatically. Note the use of [IgnoreDataMember]. It prevents the CannotBeSerializedDirectly member from being included in the implicit data contract for the class.
If you would prefer your surrogate to be private, or need to control the surrogate member names, you will need to give the containing type an explicit data contract:
[DataContract]
public class SerializeMe
{
[IgnoreDataMember]
public DoNotSerializeMe CannotBeSerializedDirectly;
[DataMember]
DoNotSerializeMeSurrogate DoNotSerializeMeSurrogate
{
get
{
if (CannotBeSerializedDirectly == null)
return null;
return new DoNotSerializeMeSurrogate { WhyAmIHereSurrogate = CannotBeSerializedDirectly.WhyAmIHere };
}
set
{
if (value == null)
CannotBeSerializedDirectly = null;
else
CannotBeSerializedDirectly = new DoNotSerializeMe(value.WhyAmIHereSurrogate);
}
}
[DataMember]
public string SomeOtherField { get; set; }
}
[DataContract]
class DoNotSerializeMeSurrogate
{
[DataMember]
public string WhyAmIHereSurrogate { get; set; }
}

How to serialize & deserialize static reference object?

i want to serialize & deserialize a object (this object has reference) using BinaryFormatter.
i have expected that 'DeserializedObject.Equals(A.Empty)' is same to below code.
but, a result is different.
in order to 'DeserializedObject == A.Empty', how to use serialize/deserialize ?
[Serializable]
public class A
{
private string ID = null;
private string Name = null;
public A()
{ }
public static A Empty = new A()
{
ID = "Empty",
Name = "Empty"
};
}
class Program
{
static void Main(string[] args)
{
A refObject = A.Empty; // Add reference with static object(Empty)
A DeserializedObject;
//Test
//before serialization, refObject and A.Empty is Same!!
if(refObject.Equals(A.Empty))
{
Console.WriteLine("refObject and A.Empty is the same ");
}
//serialization
using (Stream stream = File.Create("C:\\Users\\admin\\Desktop\\test.mbf"))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, refObject);
}
//Deserialization
using (Stream stream = File.Open("C:\\Users\\admin\\Desktop\\test.mbf", FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
DeserializedObject = (A)bin.Deserialize(stream);
}
//compare DeserializedObject and A.Empty again.
//After deserialization, DeserializedObject and A.Empty is Different!!
if (DeserializedObject.Equals(A.Empty))
{
Console.WriteLine("Same");
}
else
Console.WriteLine("Different");
}
}
The reason for this is that they are different objects! You can check this by printing their GetHashCode(). The reason for this is that in your code:
refObject is a reference to A.Empty (and thus the same object)
DeserialisedObject is NOT a copy; it is a new instance and so a
different object
However DeserializedObject should contain the same values (ID and Name). Note that refObject.ID will be the same object as A.Empty.ID; DeserialisedObject.ID will not, although is should contain (a copy of) the same data.
If you're just testing that deserialization is working, test that the values contained by DeserializedObject and A.Empty are the same.
If you have an immutable type which has one or more global singletons that represent standard values of the type (A.Empty in your case), you can implement the IObjectReference interface and make BinaryFormatter replace deserialized instances of the type with the appropriate, equivalent global singleton. Thus:
[Serializable]
public class A : IObjectReference
{
private string ID = null;
private string Name = null;
public A()
{ }
public static A Empty = new A()
{
ID = "Empty",
Name = "Empty"
};
#region IObjectReference Members
object IObjectReference.GetRealObject(StreamingContext context)
{
if (this.GetType() == Empty.GetType() // Type check because A is not sealed
&& this.ID == Empty.ID
&& this.Name == Empty.Name)
return Empty;
return this;
}
#endregion
}
And, to test:
public class TestClass
{
public static void Test()
{
A refObject = A.Empty; // Add reference with static object(Empty)
Test(refObject, true);
A dummy = new A(); // No global singleton for this one.
Test(dummy, false);
}
private static void Test(A refObject, bool shouldBeEqual)
{
Console.WriteLine(string.Format("refObject and A.Empty are {0}.", object.ReferenceEquals(refObject, A.Empty) ? "identical" : "different"));
var binary = BinaryFormatterHelper.ToBase64String(refObject);
var DeserializedObject = BinaryFormatterHelper.FromBase64String<A>(binary);
Console.WriteLine(string.Format("DeserializedObject and A.Empty are {0}.", object.ReferenceEquals(DeserializedObject, A.Empty) ? "identical" : "different"));
Debug.Assert(object.ReferenceEquals(refObject, A.Empty) == object.ReferenceEquals(DeserializedObject, A.Empty)); // No assert
Debug.Assert(shouldBeEqual == object.ReferenceEquals(refObject, DeserializedObject)); // No assert
}
}
public static class BinaryFormatterHelper
{
public static string ToBase64String<T>(T obj)
{
using (var stream = new MemoryStream())
{
new BinaryFormatter().Serialize(stream, obj);
return Convert.ToBase64String(stream.GetBuffer(), 0, checked((int)stream.Length)); // Throw an exception on overflow.
}
}
public static T FromBase64String<T>(string data)
{
return FromBase64String<T>(data, null);
}
public static T FromBase64String<T>(string data, BinaryFormatter formatter)
{
using (var stream = new MemoryStream(Convert.FromBase64String(data)))
{
formatter = (formatter ?? new BinaryFormatter());
var obj = formatter.Deserialize(stream);
if (obj is T)
return (T)obj;
return default(T);
}
}
}

Copy two identical object with different namespaces (recursive reflection)

I'm working in c# with several workspaces that have one specific class which his always the same in each workspace.
I would like to be able have a copy of this class to be able to work with it without dealing with namespaces differences.
example :
namespace1 {
class class1{
public class2;
}
class class2{
public string;
}
}
namespace2 {
class class1{
public class2;
}
class class2{
public string;
}
}
In my copied Class I've got a function to copy all data's to one of the namespace's class.
It's working if i only have c# standard types. I got exeption ( "Object does not match target type." ) as soon as I'm dealing with class2 object (which is also from different namespaces)
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;
}
Anyone do have any idea of how to deal with this kind of "recursivity reflection".
I hope eveything is understandable.
Thanks, Bye!
Edit :
I think i got it solved (at least in my mind), I'll try the solution back at work tomorrow. Taking my function out of my class and using it recursively if a property is not a standard type is maybe the solution.
BinaryFormatter does not work in .Net 4.5 as it remembers from what type of class the instance was created. But with JSON format, it does not. JSON serializer is implemented by Microsoft in DataContractJosnSerializer.
This works:
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);
}
}
and uses as follows:
var b = DeepClone<A, B>(a);
I had the similar problem. I got to use similar classes but different in terms of namespace only. As a quick solution I performed below steps and it works.
Serialize source class into XML.
In SerializedXML replace source namespace with the target one.
DeSerialize with target type.
I know there is performance overhead with above way but it is quick to implement and error free.
I got it solved , just to let you know how I did it :
This solution is sot perfect because it handle only 1 dimensions array not more.
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;
}
Hope this can help some people.
Thanks for helping everyone.
Cheers
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);
}
}
from here
Two identical or similar objects from different namespaces ?
You have this:
namespace Cars
{
public class car {
public string Name;
public void Start() { ... }
}
}
namespace Planes
{
public class plane {
public string Name;
public void Fly() { ... }
}
}
Time to apply some class 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() { ... }
}
}
And to copy, there is a copy method or constructor, but, I prefer a custom one:
namespace Vehicles
{
public class vehicle {
public string Name;
public virtual CopyFrom (vehicle Source)
{
this.Name = Source.Name;
// other fields
}
} // class
} // namespace
Cheers.
You either need to refactor all of your duplicate classes into a single shared class or implement a common interface that all of your various classes implement. If you really can't modify the underlying types, create a subclass for each that implements your common interface.
Yes, you can do it with reflection... but you really shouldn't because you end up with brittle, error prone, code.
This problem can be elegantly solves using Protocol Buffers because Protocol Buffers do not hold any metadata about the type they serialize. Two classes with identical fields & properties serialize to the exact same bits.
Here's a little function that will change from O the original type to C the copy type
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;
}
}
usage would be
namespace1.class1 orig = new namespace1.class1();
namespace2.class1 copy =
DeepCopyChangingNamespace<namespace1.class1, namespace2.class1>(orig);

Categories

Resources