I'm learning about serialization in C# and I have the basics down, but now I am trying something a little more complicated and I'm looking for some pointers on best practice (I can achieve what I want, I just want to know the 'right'/easiest/least code/most robust method of doing it).
I have a racing track which is made up of sections. Each section type inherits from a common TrackSection class. The TrackSection class holds a lot of data on geometry and other things that I don't want to save out and it needs some context information when the constructor is called, so I have implemented the ISerializable interface and provided my own methods to handle (de)serialization. The classes that inherit from TrackSection are a lot simpler, and I would be happy for all their fields to be serialized automatically, but I assume that since the base class is ISerializable they probably need to do it manually as well (I have added the deserialization constructor and call the base class's deserialization constructor in each). When it comes to serializing though I'm not sure what to do, I would have expected ISerializable's GetObjectData() method to be virtual so I could extend the serialization in sub-classes. Do I simply need to implement my own virtual method that is called from the base class's GetObjectData(), or am I going about this all wrong?
As I say, I have it working but any better solution or any general tips about what I'm doing would be much appreciated, as I can't help but feel my solution is a little more complicated than it needs to be. Thanks.
Unless you're doing something where you need to implement ISerializable, you could, instead just mark the class with the Serializable attribute and mark the fields that you don't want serialized as NonSerialized
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).
In the example I'm thinking of I have about 4 lines of code that could be encapsulated by a function, and this function will surely be used in other classes in the same hierarchy.
I have the following options for reusing that code:
Copy paste the function around to the classes that need it.
Make a base class for the classes that need the function and put it there.
Make a class that contains the function which gets passed into the classes that need it through DI or is just a member of the class. (seems like major overkill)
Make a static utility class and put that method in it.
I definitely wouldn't do 1 or 4. I would have done 2 in the past but I'm trying to keep to the composition over inheritance principle so I'm leaning towards 4 however it seems like a lot for something that will most likely never be used outside the hierarchy and is only 4 lines. I know this is very nitpicky but I want to figure out the right way to do it.
Inheritance was created for a reason. The fact that it has been overused doesn't mean that it doesn't have legitimate uses. The key is that whether you use it should not depend on whether you can get easy reuse out of it, but whether it makes sense for it to belong to the base class, based on what your base class represents.
Without better understanding what your classes are, and what the method is that you're trying to reuse, I can't give specific advice in your particular case. But think of it this way: When you say it will "most likely never be used outside the hierarchy," is that because it purely just doesn't make sense outside of that hierarchy? Or is it just that you don't think somebody's going to build something that happens to use this feature, even though it could conceivably make sense outside of the hierarchy?
If this method would make any sense outside of the specific hierarchy you're talking about, I would suggest approach #3.
And of course, all of this assumes that your class hierarchy is really a hierarchy in the first place. Another common abuse of inheritance is when people force a hierarchy on objects that don't need to be hierarchical in the context of their application.
I agree that composition is a better option than inheritance IN GENERAL. But composing your objects with some logic, perhaps via the strategy pattern, is a different issue than reusing the same code by multiple classes.
If those classes that need this functionality all have the same base class, then it makes sense to put it in the base class. It's not like the subclasses need to know the inner workings of the base class to make this call.
If various subclasses need different versions of this code, then creating behaviors via the strategy pattern (using composition) is the way to go. But I'm making an assumption that the same code satisfies every subclass.
I wouldn't do #4 because then that code is available to other classes that have no business calling it. If the code is in the base class, then you can make it protected and therefore only available to the classes that need it.
if such function arguments are going to be fields of the classes, than it is intended to be operating on your class state and thus should be a member of the base class that addresses such a manipulation.
if you operate on some data that makes sense outside of your hierarchy or from several branches of the hierarchy and meaning of the parameters is not bound to object state make it a function in a utility class.
If it's specifically related to your class hierarchy, use a base class. If not, use option 4. There is no need for composition here.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Interface vs Abstract Class (general OO)
Following are the confusions which I have between interface, abstract and normal class-
I know an abstract class can have a method with no implementation, but what is the harm in declaring method as virtual in base class with some dummy implementation and over ride in derived class. Looking for a practical scenario where answer can be validated?
Why we need an interface when we have abstract class, I know with interface we can have multiple inheritance, and have goggled about various theoretical reasons, looking for practical scenarios where abstract class just cant help and you have to go for interface?
Is having an abstract class and interface is not an overhead?
Practical Examples
I think you are thinking too hard. Its like looking at a fork and a spoon and worrying about when to use when. There is no right answer, just use the one that makes sense to you for what you are doing. Many paths to getting there.
Here is how I use these in the real world (fortune 500 companies etc...)
Interfaces allow you to add as many as you want to a class. They essentially allow you to bind to any contract as much as you want. They are as minimal as you get. An example I used this in was a music encoder service where it just had some simple properties and methods that each encoder type needed. I later added more interfaces as other requirements came into play but I didn't want to break the code for other parts not needing to know or care about the new interface. The encoders were very loosely coupled and could have more than one contract so this made sense for me. The main thing about interfaces is when you use them, don't keep changing them as it defeats the purpose of the interface, rather make a new one. Interfaces are the best for plugin type of development.
Abstract classes are kind of cool because you can have some base implementation already cooked in there but you are essentially saying "but you still have to make this part" as its the responsibility of the class to implement this. This could be for a "save" method for example. Let's say you had some abstract class that handled data in the same way but you had many commonalities in the underlying abstract class that did a lot of work but you had a requirement that each inherited type save its own data in its own format needed for example. This could relate to a networked item that saved things in facebook and twitter or another item that saved things in a database and a file system but the core code always hit a central db to say it was saved with last date modified.
So sorry, I was bored, lots of typing. But that's how I have used them.
There are scenarios where there is no "correct" dummy implementation. In the System.IO.Stream case (an abstract class), for example, what would be a reasonable implementation for Read or Write? Throw? Do nothing? Or the many methods in the System.Xml.XmlReader class - what's a reasonable implementation for a Depth, or Read of an arbitrary XML reader? By making methods in a class abstract (and not virtual) the author of the class is making a statement that anyone who derives from that class must think about what to do for those methods, and the abstract qualifier enforces that.
The practical reason is exactly what you said - multiple inheritance. If IEnumerable<T> were an abstract class, for example, there would be many cases where we'd want to be able to enumerate over the elements of an object but couldn't because the object already inherited from some other class. The more theoretical reason is that interfaces usually define behavior, while classes define a cluster of objects, but for the purposes of your question the practical reason is more, well, practical.
I don't understand your question. Overhead in which sense?
Each has its own purpose. You use an interface when you don't want to define any specific implementation. It only provides an "interface" to an object, that is the methods and properties that make up a public definition. An object can inherit multiple interfaces. A good example of this is the List<> object. List<> implements several interfaces, such as IEnumerable, IList, ICollection, IEnumerable<>, IList<>, and ICollection<>.
Each of these has different methods, and different properties, and are used for different purposes. You could not do this with an abstract class. You can cast a List<> to any of those interfaces and use them without knowing the exact implemenation of them. This is particularly useful with a concept known as Dependency Injection, but has many other uses.
An abstract class is useful when you want to define part of the implementation of an object, but want to leave other parts up to the derived class. One key thing to remember about abstract classes is that they cannot be instantiated by themselves, because they typically lack a complete implementation as well as the fact that abstract keyword tells the complier it can't be instantiated. Yes, you can supply dummy implementations, but why? The whole point is that abstracts are.. well.. abstract.
Imagine you have a class Cat, and this class derives from a class Animal. There is no such thing as an Animal object, it's just a "type". You can't instantiate an Animal because there is no actual Animal in the real world, there are only creatures that are of the type Animal. You can treat different creatures as a common Animal type, but there can't exist a real Animal, it's just a concept.
An Animal would be an abstract type, because the concept of the Animal is abstract. The same is true in software. You might have the concept of an object, such as a Stream. Is it a NetworkStream? A FileStream? A MemoryStream? Stream is just a concept. An interface is also just a concept, but the unlike an abstract class an Interface cannot have any implementation.
So think of an abstract class as a concept with some implementation, and an interface as a concept without any implementation.
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.
In C#, is it possible to extend a class that has no constructors?
Maybe I'm thinking about this incorrectly and just need a kick in the crotch. I have a Silverlight class that extends System.Windows.Media.Transform, With the official release of Silverlight 2, Transform now has no constructor. So, when I compile my class, I get an error saying that 'The type '...Transform' has no constructors defined.'
Is it still possible to extend this class in a useful way? If not, I'm going to be drawing an awful lot of sad faces.
The sole constructor to Transform is internal, so you can't derive from it yourself.
Hiding all public constructors is a technique used to prevent subclassing and force developers to use the class as intended. It may be the implementor wants you to use an Adapter or Facade or even a Proxy at the time of extension.
There may be important lifecycle details in the constructor that require the use as the original implementor intended, or it may be an oversight by the developer.
I've seen attempts at conversion to the Factory pattern where this is done in a manner that prevents subclassing. I.e. there is no protected constructor made available to subclasses. Sometimes advanced object patterns can strain the in-built capabilities of a language.
It is impossible that some class has no constructor. Every class has at least one AFAIK. If you don't write it C# compiler will insert an default (parameterless) constructor for you.
As long as its not sealed, you should be able to extend it.