I understand DTO's strict definition is to serve as container to transport data, it shouldn't have any behavior. However, I have faced a situation with a need to clone the DTO, two options:
1. create a Clone method (ICloneable?) in DTO
2. create generic utility class to clone DTO
I currently use option #2. However, I think #1 is acceptable provided there are no logic in DTO. I would like see if any of you faced a similar situation with DTO that required basic operations like Clone, ToString, especially DTOs that had inheritance. Thanks.
If it is a DTO, it should be designed for serialization - in which case your best option is to serialize it via whatever process it is designed, and rehydrate a clone from there. It is pretty rare that this would be a performance issue.
Clone is an operation that is not very commonly needed. However, should you truly need to clone objects it's perfectly acceptable to implement it directly on the object. This will allow you to access the protected MemberwiseClone feature in relation to ICloneable
Cloning is frequently implemented with MemberwiseClone. See Cannot access protected member 'object.MemberwiseClone()' .
If you need deep graph cloning, look into the BinaryFormatter to clone your object. Or look into changing your model to not expect cloning.
Related
I tried the SOLID architecture within my last project.
I have an Interface called ILog and a class Logthat implemented ILog. (In my understanding that should be done to follow the Open/Closed principle)
In order to stay open for extensions I implemented the front end via List<ILog> instead of with the firm implementation List<Log>.
Serializing the List<ILog> is no problem, but deserializing is. I understand why of course, because the deserializer does not know which implementation class it should use.
Question:
How to know into which concrete type to deserialize an object that was serialized through an interface reference?
Serializing the List is no problem, but deserializing is.
If you are deserializing you necessarily need to somehow communicate to your serializer which conrete representation of your interface to use. In case of Json.NET you could use the JsonConstructorAttribute (see also this answer) or resolvers in combination with dependency injection.
Question: What does it help me to work with List if I have to define the specific implementation-class for data storage / data import anyways?
Interfaces decouple your code from the actual implementation, which results in various benefits. For example in terms of unit testing they make mocking easier (since you can satisfy the interface with a mocked instance instead of being forced to use the "real" class). Also Interfaces allow you to benefit from covariance/contravariance, which you wouldn't have with a classes in C#. For further reading on the benefits of interfaces, have a look at the various answers to this question or see this blog post.
The above being said, interfaces always introduce a certain level of overhead/abstraction and you need to evaluate per case/situation, whether they make sense or not.
What would be the best way to handle the data-storage of interface objects or are they only used at runtime?
You necessarily need to store concrete representations, which means at the time of persistance, you need to decide which concrete implementation to use for storage (and later deserialization).
I want to deserialize an object graph in C#, the objects in the graph will have object and collection properties, some of the properties may be private, but I do not need to worry about cyclic object references. My intent is to use the deserialized object graph as test data as an application is being built, for this reason the objects need to be able to be deserialized from the XML prior to any serialization. I would like it to be as easy as possible to freely edit the XML to vary the objects that are constructed. I want the deserialization process not to require nested loops or nested Linq to SQL statements for each tier in the object graph.
I found the DataContractSerializer lacking. It can indeed deserialize to private fields and properties with a private setter but it appears to be incredibly brittle with regard to the processing of the XML input. All it takes is for an element in the XML to be not in quite the right order and it fails. What's more the order it expects the data to be declared in does not necessarily match the order the object members are declared in the class declaration, making it impossible to determine what XML will work without having the data in the objects to start with so that you can serialize it and check what it expects.
The XmlSerializer does not appear to be able to serialize to non-public data of any type.
Since the purpose is to generate test input data for what might be quite simple applications during development I'd rather not have to resort to heavyweight ORM technologies like Entity or Nhibernate.
Is there a simple solution?
[Update]
#Chuck Savage
Thanks very much for your reply. I'm responding in this edit due to the comment character limit.
In the technique you suggested the logic to deserialize each tier of the object hierarchy is maintained in each class, so in a sense you do have nested Linq to SQL just spread out across the various classes involved. This technique also maintains a reference to the XElement from which each object gets its values in each class, so in that sense it isn't so much deserialized as just creating a wrapper around the XML. In the scenario I have in mind I'd ideally like to be deserializing the actual business objects the application will use so an XML wrapper type object like this wouldn't work very well since it would require a distinctly different implementation for test usage compared to production usage.
What I'm really after is something that can do something akin to what the XmlSerializer can do, but which can also deserialize private fields, (or at least properties with no setter). The reason being that the XmlSerializer does what it does with minimal impact on the 'normal' production use of the classes involved (and hence no impact on their implementation).
How about something like this: https://stackoverflow.com/a/10158569/353147
You will have to create your own boilerplate code to go back and forth to xml, but with the included extensions that can be minimized.
Here is another example: https://stackoverflow.com/a/9035905/353147
You can also search my answers on the topic with: user:353147 XElement in the StackOverflow search.
On my own object I can add the metatag [Serializable] to make it serializable. Now I use a 3rd party library that I need to be serializable. I inspected the code and it should not be a problem. Is there a way to fix this without altering the 3rd party code?
My advice would be: serialize data, not implementation. The fact of the existence of a 3rd-party object is nothing to do with the data; that is an implementation detail. As such, I always offer the same advice: if serialization ever gets complex, the first thing to do is to introduce a separate DTO model that represents the data in isolation of the implementation, and just map the current state to that DTO. This allows you to handle implementation changes without impact on the storage, and allows otherwise non-serializable objects to be serialized.
Some serializers offer workarounds - for example with protobuf-net you can a: supply the serialization information for any type at runtime, and b: supply a "surrogate" to use automatically when it gets tricky, but - using a DTO model is simpler and easier to maintain.
Your use of [Serializable] suggests BinaryFormatter; in my opinion, this is almost never a good choice for any kind of storage, since BinaryFormatter relies on implementation details. It works nicely for passing data between two in-sync app-domains, though
If the types are public you should be able to use the XmlSerializer to do what you want.
There's more information on this here
Serializes and deserializes objects into and from XML documents. The
XmlSerializer enables you to control how objects are encoded into XML.
Exactly take your subclass and make it serializable.
[Serializable] public class Foo: Bar {}
Write an adapter or be prepared to do something more extreme like disassembling the assembly, injecting the serializable attribute and reassembling.
whenever I try to serialize an object that has an IEnumerable collection I get a big dirty error telling me it can't serialize it because it's an interface. Now I get why it's happening but it raises some other questions for me. Like if I intend on having collections within my objects AND I want to serialize them do I need to resort to
Using List<>, CollectionBase, ReadOnlyCollectionBase in my objects.
Making my objects implement the IXmlSerializable interface.
Decorating my classes with horrible attributes.
Writing my own serializer.
What is the best practice way to go?
Speaking as a serializer author, I know exactly why it gets very hard to robustly work just from IEnumerable<T>, especially for "get-only" properties. You might try IList<T> (although it wouldn't amaze me if it wants a concrete type such as List<T>/T[]), but I suspect the real problem here is that you trying to use one model to do two things, and are unhappy at having to compromise to do it.
Fine: if you don't want to compromise your domain model, write a separate DTO model that is used for serialization, and just map between them. This is usually trivial, and will allow the serializer and the domain model to each excel at their one job. It will also help immensely when you need to "version" the system or introduce a different serializer (JSON, protobuf, etc).
Re your bullets:
I suspect any concrete list type (even your own) with Add etc will work
I don't recommend that to anyone - it is painful to do reliably
nothing ugly about attributes; again, I suspect your complaint is about attributing your domain model - so: fine, don't do that - have a separate model; you can actually do all this at runtime, but it is much more work (see XmlAttributeOverrides, but watch out for leaking assemblies if you do this)
don't underestimate how much work that is; the basics - seductively easy; but the non-trivial scenarios can be brutal
For use interface or derivade classes you MUST use the XmlSerializer(Type type, Type[] extraTypes) constructor.
In extraTypes you MUST include all possible classes which can implement the interfaces in your classes.
what is the best Solution for mapping class object to lightweight class object by example:
Customer to CustomerDTO both have the same properties names, i was thinking of the best optimized solution for mapping between them , i know reflection slow me down badly , and making methods for every mapping is time consuming so any idea ?
thanks in advance.
AutoMapper. There's also ValueInjecter and Emit Mapper.
If reflection is slowing you down too much, try Fasterflect: http://www.codeproject.com/KB/library/fasterflect_.aspx
If you use the caching mechanism, it is not much slower than hand-written code.
I've been playing about with this, and have the following observations. Should Customer inherit from CustomerDTO or read/write to a CustomerDTO? I've found that some DTO generators only generate dumb fixed size array collections for vectors of data items within the DTO others will allow you to specify a LIST<> or some such collection. The high-level collection does not need to appear in the serialised DTO but effects which approach you take. If your solution adds high-level collections then you can inherit if it doesn't then you probably want to read/write to a intermediate DTO.
I've used Protocol Buffers and XSDObjectGenerator for my DTO Generation (at different times!).
A new alternative is UltraMapper.
Is faster than anything i tried up to Feb-2017. (2x faster than Automapper in any scenario)
It is more reliable than AutoMapper (no StackOverflows, no depth limits, no self-reference limits).
UtraMapper is just 1300 lines of code instead of more than 4500+ of Automapper and it is easier to understand, maintain and contribute to the project.
It is actively developed but at this moment it needs community review.
Give it a try and leave a feedback on the page project!.