On numerous occasions I’ve been involved in projects, where I’ve had an instance of a given object type present in one namespace and the need to convert it to an object type with exactly the same signature, but in another namespace.
Usually, in a scenarios of dealing with web services – where different web services, logically refer to the same types, but the proxy classes are generated in different namespaces – making the incompatible.
The non-technical approach, would be to convert the instance types with helper methods. Copying each data field/property one-by-one. For large and deeply nested structures, this quickly becomes a dead end.
To solve this problem, I use the less-known serialization trick:
Serialize the source instance
Deserialize the source instance, but to the destination instance type
This of course requires the types to be serializable, if you’re dealing with web service proxies – this is not an issue – as these will most probably already be serializable 🙂
The C# code for doing the conversion:
/// <summary> /// Converts a given instance (of a given type) to the same type, but present in another namespace /// (requires types to be serializable). /// </summary> /// <typeparam name="T">The type to convert to</typeparam> /// <param name="instance">The instance containing the source type</param> /// <returns>The covnerted type</returns> private static T ConvertType<T>(object instance) { if (instance == null) { throw new ArgumentNullException("instance"); } var typeSource = instance.GetType(); var typeDestination = typeof(T); T result = default(T); // We're using a Memorystream for the serialization magic using (var ms = new MemoryStream()) { // Create the serializer for the incoming type var serializer = new XmlSerializer(typeSource); // Create a XML text writer, and serialize the incomming instance to memory var tw = new XmlTextWriter(ms, Encoding.UTF8); serializer.Serialize(tw, instance); // Rewind the MemoryStream to the beginning. ms.Position = 0; // Now, create the deserializer for the destination type var deserializer = new XmlSerializer(typeDestination); using (var reader = new XmlTextReader(ms)) { try { result = (T)deserializer.Deserialize(reader); } catch (Exception ex) { throw new ApplicationException(String.Format("Converting from type: {0}->{1} failed", typeSource.FullName, typeDestination.FullName), ex); } } } return result; }
Example:
namespace OneNamespace { [Serializable] public class Person { public string Name; public int Age; } } namespace OtherNamespace { [Serializable] public class Person { public string Name; public int Age; } } var person1 = new OneNamespace.Person() {Name = "Henrik", Age = 25}; // Obviously, casting is NOT an option :-) //OtherNamespace.Person person2 = (OtherNamespace.Person)person1; var person2 = ConvertType<OtherNamespace.Person>(person1);