0

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?

Luchspeter
  • 744
  • 7
  • 24
  • 1
    Guidelines like SOLID do you no good if they don't fulfill your needs. The question to answer is not whether you're following SOLID principles; it's whether you really need that `ILog` interface or not. – Robert Harvey Dec 14 '18 at 16:10
  • Why do you want to serialize a logger? Or more generically, why are you using an interface where you want to (de)serialize something? You can't deserialize a serialized `FooFrobber` as a `BarFrobber` even though they both implement `IFrobber`. – CodeCaster Dec 14 '18 at 16:10
  • I thaught it might be a good idea to stay open for future extensions since this project is going to be alive for quite some time. – Luchspeter Dec 14 '18 at 16:11
  • Why not require the implementer of `ILog` to also implement deserializing? After all, they know their impl best. – Lynn Crumbling Dec 14 '18 at 16:11
  • It actually was not a Log class - for simplicity i chose a simple word... – Luchspeter Dec 14 '18 at 16:12
  • 1
    Extensibility, interfaces and serialization don't have to have to do with each other. Please ask a very concrete question as this sounds too vague. If, for example, your question is _"How to know into which concrete type to deserialize an object that was serialized through an interface reference"_, the answer could be _"Save the `Type` info with it when serializing"_. – CodeCaster Dec 14 '18 at 16:12
  • @CodeCaster Yes I thing that might be the answer! I will update my question correspondingly thank you! Do you want to change your comment into the answer so I can mark it accordingly? – Luchspeter Dec 14 '18 at 16:15
  • The full answer somewhat depends on the serializer you're using. For instance, [JSON.NET has built-in methods for this type of thing](https://stackoverflow.com/a/40403520/215552), and if you're using [WCF, there's a different method](https://stackoverflow.com/q/3167932/215552), etc.. – Heretic Monkey Dec 14 '18 at 16:25

1 Answers1

1

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).

Felix K.
  • 14,171
  • 9
  • 58
  • 72