1

I am trying to return a JSON object from a Web API call. I would like to return this object in terms of the interface it implements, so:

response.Content.ReadAsAsync<IThingy>().Result

I'm getting this error:

Could not create an instance of type IThingy. Type is an interface or abstract class and cannot be instantiated.

Really this is just the same as the problem in this question, except that I want to deserialize an object that implements an interface, rather than deserializing a property whose type implements an interface.

How can I do this deserialization?

Community
  • 1
  • 1
Gigi
  • 28,163
  • 29
  • 106
  • 188

1 Answers1

3

You need to deserialize to a concrete class because the behaviour of that class must be defined. You need a Thingy : IThingy at which point I would do:

IThingy result = response.Content.ReadAsAsync<Thingy>().Result;

Why must you do this? Interfaces define no behaviour, only signatures of methods and properties. Say you were able to deserialize directly to IThingy and it had a method DoMath(int x, int y) - what math would be done? There would be no defined behaviour. That's why you must choose a concrete class.

Haney
  • 32,775
  • 8
  • 59
  • 68
  • Yes, the interfaces I am passing are indeed signatures - because I am passing data transfer objects (no methods). Passing the interfaces reduces coupling on their actual implementation. – Gigi Apr 10 '14 at 13:35
  • Of course I do have concrete classes, but I want to pass their instances in terms of the interfaces. – Gigi Apr 10 '14 at 13:36
  • 1
    @Gigi this is a common misunderstanding. Interfaces are a signature for concrete types. Decoupling is all about SOLID AKA coupling to interfaces vs concrete types. However, at some point SOMETHING must know what types to use. In an inversion-of-control scenario the topmost class/startup will know and resolve dependencies. This deserialization is ANOTHER entry point for your application which must also know about your concrete types. This is normal. You cannot avoid deserializing to a concrete type unless you deserialize to a `dynamic` type, which I would surely not recommend. – Haney Apr 10 '14 at 13:37
  • If you're very concerned, just create an interface like `IThingyDeserializer` and have a concrete `Deserializer` where `T : Thingy` which will deserialize to the concrete type `Thingy`... Then use that directly to keep concretes out. Note that this would be quite a lot of overkill, however. – Haney Apr 10 '14 at 13:39
  • Thanks. Just one question... then why is it okay to deserialize interface properties (as per link in question)? – Gigi Apr 10 '14 at 14:11
  • Because the deserializer sees the concrete types in the constructor and property assignment, and is smart enough to choose them to be used during deserialization. It's a "hack". – Haney Apr 10 '14 at 14:12