Is there simple way transform one object in another, first defined in application object model and another defined in web service refference. Definitions of two objects are the same.
If you are using WCF, you can actually share types defined in a WCF service with clients of that service.
See the section Using the Employee Class on the Client of this article:
http://10rem.net/blog/2009/07/13/sharing-entities-between-wcf-and-silverlight
Types defined in your web service become available to (.NET) clients consuming them by electing to reuse types defined on the WCF side.
UPDATE:
As promised in one of my comments, here's code to create a copy of an object using serialization. I'm including both a variant that expects a specific class, and a variant that uses generics to support any serializable type. You can replace DataContractSerializer with BinarySerializer in many cases.
static public Organization Copy(Organization org)
{
MemoryStream stream1 = new MemoryStream();
//Serialize the Record object to a memory stream using DataContractSerializer.
DataContractSerializer serializer = new DataContractSerializer(typeof(Organization));
serializer.WriteObject(stream1, org);
stream1.Position = 0;
//Deserialize the Record object back into a new record object.
Organization orgCopy = (Organization)serializer.ReadObject(stream1);
return orgCopy;
}
static public T Copy<T>(T obj)
{
MemoryStream stream1 = new MemoryStream();
//Serialize the Record object to a memory stream using DataContractSerializer.
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(stream1, obj);
stream1.Position = 0;
//Deserialize the Record object back into a new record object.
T objCopy = (T)serializer.ReadObject(stream1);
return objCopy;
}
you could probably map the objects one to the other having an helper class which copies/assigns member to member.
In general the best approach is anyway to avoid this kind of transformation especially if objects are the same as in your case.
This can be avoided with a good design, for example in WCF specifying data contracts and having such classes implementing a common interface shared in both service and application, then of course you should program in all the places against the interface and not the class which implements it.
for old XML web services, when data contracts were not available yet, something can still be done using interfaces but then it also depends on the way you expose your types, if the service returns a class of its own type or of a type defined in a common class/interface library.
You could use AutoMapper to do this:
AutoMapper is an object-object mapper ... AutoMapper works best as
long as the names of the members match up to the source type's
members. If you have a source member called "FirstName", this will
automatically be mapped to a destination member with the name
"FirstName".
Related
I'm using a 3rd party library from a company called oh let's say Mobi. They offer domain objects and a client that accepts THEIR domain objects, internally serializes it, and posts it to a rest endpoint.
I wanted to architect my code so that I'm not completely dependent upon them in case I want to switch out their library for something custom built or another 3rd party library. So I created identically named classes and inherited them from the corresponding 3rd party class.
for example:
public class Patient : Mobi.Model.Patient, IResource
{
}
I created IResource so I could have factory methods and polymorphism and all that jazz. So here's my issue, I can't use their client to post MY domain objects. I need to convert my domain object to their domain object to use their client.
For example:
var client = new Mobi.MobiClient();
IList<IResource> resources = new List<IResource>();
resources.Add(new Patient()) // my Patient class not theirs
resources.Add(new Doctor()) // my Doctor class not theirs
foreach(var resource in resources)
{
var mobiResource = MethodToConvertIResourceToTheDerivedResourceAndMapItToTheirResource(resource)
client.Post(mobiResource)
}
So how would I implement the method to convert a base class to a derived class and then map it to an identical class?
I could have a bunch of "is" statements and then use something like AutoMapper but I was wondering if there was something that was more dynamic or easier. Also wanted to know if this is a bad way to do things.
I have a utility that converts an xml file to a class object:
public static T CreateClassFromXml<T>(string fileName, string root) where T : class
{
fileName.ThrowNullOrEmpty("fileName");
File.Exists(fileName).ThrowFalse(string.Format("File '{0}' could not be found", fileName));
var serializer = new XmlSerializer(typeof(T), new XmlRootAttribute() { ElementName = root });
using (var reader = XmlReader.Create(fileName))
{
return (T)serializer.Deserialize(reader);
}
}
The utility reads the xml and creates a class T. Using the above code is there any way I can validate the created class other than writing a wrapper class around it? I need to ensure that data is populated for all mandatory fields.
There are no built in facilities in XmlSerializer to do this. You can do it yourself with reflection. Since XmlSerializer loads just the public properties and fields, you can iterate over all public properties and fields of the class and make sure they all hold data. You'll have to decide how to handle value types (int, DateTime, etc...) because it's not obvious when the have been loaded or not. You will also have to dive in recursively into reference types.
If you need to mark just specific properties\fields as mandatory, you can add your own attribute and decorate the class members with it. In runtime, you will only process properties which have the attribute set.
In short, unless you need a generic mechanism for many different scenarios, better do it manually for the properties you have to validate.
I have an application which supports multiple types and versions of some devices. It can connect to these devices and retrieve various information.
Depending on the type of the device, I have (among other things) a class which can contain various properties. Some properties are common to all devices, some are unique to a particular device.
This data is serialized to xml.
What would be a preferred way to implement a class which would support future properties in future versions of these devices, as well as be backwards compatible with previous application versions?
I can think of several ways, but I find none of them great:
Use a collection of name-value pairs:
pros: good backward compatibility (both xml and previous versions of my app) and extensibility,
cons: no type safety, no intellisense, requires implementation of custom xml serialization (to handle different value objects)
Create derived properties class for each new device:
pros: type safety
cons: have to use XmlInclude or custom serialization to deserialize derived classes, no backward compatibility with previous xml schema (although by implementing custom serialization I could skip unknown properties?), requires casting for accessing properties in derived classes.
Another way to do it?
I am using C#, by the way.
How about something similar to a PropertyBag ?
If you're not limited to interoperability with an external schema, then you should use Runtime Serialization and the SoapFormatter. The pattern for runtime serialization permits derived classes to specify which of their properties need to be serialized and what to do with them when deserialized.
The XML Serializer requires XmlInclude because, in effect, it needs to define the schema to use.
I like name/value sets for this sort of thing.
Many of your cons can be dealt with -- consider a base class that acts as a general name/value set with no-op methods for validating incoming name/value pairs. For known sets of names (i.e. keys), you can create derived classes that implement validation methods.
For example, Printer may have a known key "PrintsColor" that can only be "true" or "false". If someone tries to load PrintsColor = "CMYK", your Printer class would throw an exception.
Depending on what you're doing, you can go a few different ways in terms of making the validation more convenient -- utility methods in the base class (e.g. checkForValidBoolean()) or a base class that accepts name/type information in its constructor for cleaner code in your derived classes, and perhaps a mostly automated XML serialization.
For intellisense -- your derived classes could have basic accessors that are implemented in terms of the key lookup. Intellisense would present those accessor names.
This approach has worked well for me -- there's sort of a short-sightedness to classic OO design, especially for large systems with plugged-in components. IMO, the clunkier type checking here is a big of a drag, but the flexibility make it worthwhile.
I believe that creating derived properties is the best choice.
You can design your new classes using xml schema. And then just generate the class code with xsd.exe.
With .net isn't hard to develop a generic class that can serialize and deserialize all types to and from xml.
public static String toXmlString<T>(T value)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
try { xmlSerializer.Serialize(stringWriter, value); }
catch (Exception e)
{
throw(e);
}
finally { stringWriter.Dispose(); }
String xml = stringWriter.ToString();
stringWriter.Dispose();
return xml;
}
public static T fromXmlFile<T>(string fileName, Encoding encoding)
{
Stream stream;
try { stream = File.OpenRead(fileName); }
catch (Exception e)
{
e.Data.Add("File Name", fileName);
e.Data.Add("Type", typeof(T).ToString());
throw(e);
}
BufferedStream bufferedStream = new BufferedStream(stream);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
TextReader textReader;
if (encoding == null)
textReader = new StreamReader(bufferedStream);
else
textReader = new StreamReader(bufferedStream, encoding);
T value;
try { value = (T)xmlSerializer.Deserialize(textReader); }
catch (Exception e)
{
e.Data.Add("File Name", fileName);
e.Data.Add("Type", typeof(T).ToString());
throw(e);
}
finally
{
textReader.Dispose();
bufferedStream.Dispose();
}
return value;
}
Programatically speaking, this sounds like it might be a job for the Decorator Pattern. Essentially, you have a super class which defines a common interface for all these types of devices. Then you have decorator classes which have other properties which a device might have. And, when creating these devices, you can dynamically add these decorations to define new properties for the device. Graphically:
You can look at the Wikipedia page for a more detailed description. After that, it would just be a matter of doign some serialization to tell the program which decorators to load.
The general idea of what you're trying to accomplish here is precisely what the EAV pattern solves. EAV is a pattern most commonly used in database development but the concept is equally valid for applications.
My generic method needs to serialize the object passed to it, however just insisting that it implements ISerializable doesn't seem to work. For example, I have a struct returned from a web service (marked with SerializableAttribute) that serializes to xml just fine, but, as expected, the C# compiler complains.
Is there a way I can check the object is serializable before attempting to serialize it, or, better still, a way of using the where keyword to check the object is suitable?
Here's my full method:
public static void Push<T>(string url, T message)
where T : ISerializable
{
string xml = SerializeMessage(message);
// Send the message to Amazon SQS
SendMessageRequest sendReq = new SendMessageRequest { QueueUrl = url, MessageBody = xml };
AmazonSQSClient client = new AmazonSQSClient(S3User, S3Pass);
client.SendMessage(sendReq);
}
And SerializeMessage:
private static string SerializeMessage<T>(T message)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (StringWriter stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, message);
return stringWriter.ToString();
}
}
If this isn't possible, what's the best way to perform a check that an object is serializable at runtime?
You can't do this totally via generic constraints, but you can do a couple things to help:
1) Put the new() constraint on the generic type (to enable the ability to deserialize and to ensure the XmlSerializer doesn't complain about a lack of default ctor):
where T : new()
2) On the first line of your method handling the serialization (or constructor or anywhere else you don't have to repeat it over and over), you can perform this check:
if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
throw new InvalidOperationException("A serializable Type is required");
Of course, there's still the possibility of runtime exceptions when trying to serialize a type, but this will cover the most obvious issues.
I wrote a length blog article on this subject that you may find helpful. It mainly goes into binary serialization but the concepts are applicable to most any serialization format.
http://blogs.msdn.com/jaredpar/archive/2009/03/31/is-it-serializable.aspx
The long and short of it is
There is no way to add a reliable generic constraint
The only way to check and see if an object was serializable is to serialize it and see if the operation succeeds
The only way to know if an object is serializable is to try to serialize it.
In fact, you were asking how to tell if a type "is serializable", but the actual question will be with respect to objects. Some instances of a type may not be serializable even if the type is marked [Serializable]. For instance, what if the instance contains circular references?
Instead of
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
try
XmlSerializer xmlSerializer = new XmlSerializer(message.GetType());
C# 8 and up allows the unmanaged constraint to limit types to structs that have nothing but value types in them (on any nested level). What we really want is:
public class MyClass<T> where T : ISerializable or unmanaged
But unfortunately, at the time of writing C# does not support this syntax (constraints are always AND, separated by commas).
A workaround could be a ValueWrapper class:
public class ValueWrapper<U> : ISerializable where U : unmanaged
This takes a U for a constructor argument. It has one property U Value. Now you can treat value types as ISerializable simply by wrapping them in a ValueWrapper.
Is it somehow possible to use the XmlSerializer to deserialize its data into an existing instance of a class rather than into a new one?
This would be helpful in two cases:
Easily merge two XML files into one object instance.
Let object constructer itself be the one who is loading its data from the XML file.
If the is not possible by default it should work by using reflection (copying each property after the deserialisation) but this would be an ugly solution.
Basically, you can't. XmlSerializer is strictly constructive. The only interesting thing you can do to customize XmlSerializer is to implement IXmlSerializable and do everything yourself - not an attractive option (and it will still create new instances with the default constructor, etc).
Is xml a strict requirement? If you can use a different format, protobuf-net supports merging fragments into existing instances, as simply as:
Serializer.Merge(source, obj);
I think you're on the right track with the Reflection idea.
Since you probably have a wrapper around the XML operations anyway, you could take in the destination object, do the deserialization normally into a new object, then do something similar to cloning by copying over one by one only the properties holding non-default values.
It shouldn't be that complex to implement this, and it would look to consumers from the rest of your application just like in-place deserialization.
I hit the same problem a few weeks ago.
I put a method Deserialize(string serialized form) in the ISelfSerializable interface that an entity class of mine implemented. I also made sure the interface forced the class to have a default constructor.
In my factory I created an object of that type and then deserialized the string into it.
This is not thread safe thing to do... But you can do:
[Serializable]
public class c_Settings
{
static c_Settings Default;
public static SetExistingObject(c_Settings def)
{
Default = def;
}
public string Prop1;
public bool Prop2;
public c_Settings()
{
if (Default == null)
return;
MemberInfo[] members = FormatterServices.GetSerializableMembers(typeof(c_Settings));
FormatterServices.PopulateObjectMembers(this, members, FormatterServices.GetObjectData(Default, members));
}
}
This way you feed your object to deserialiser and deserialiser only overwrites whatever is written in .xml.