Cast an anonymous type with same properties to an interface

2.4k views Asked by At

I am trying to cast anonymous type with the same property to an interface, but it's coming up with an error:

Unable to cast object of type '<>f__AnonymousType104`1[System.Int32]' to type 'IHasFiles'.

 public interface IHasFiles
 {
    int FileMasterId { get; }
 }

 var entity = new { FileMasterId = fileMasterId }.CastOrDefault<IHasFiles>();
 // This is the line where I get the error
1

There are 1 answers

4
Lasse V. Karlsen On BEST ANSWER

That is because interface implementation is explicit, not dynamic.

You can't cast an object to an interface reference simply because it has the same members, the type of that object has to explicitly implement the interface as well.

Anonymous types aren't castable to anything, other than object, dynamic (an object in disguise) or its own type, which is also a bit tricky since you don't exactly know the type (but there are ... hacks for this).

So no, you can't do that.

What you're looking for is commonly known as "duck typing", aka "if it walks like a duck, and if it quacks like a duck, then for all intents and purposes, it is a duck". This is not supported with stock C# or .NET but can be "mimicked" using code.

If you require an object that implements a specific interface you must declare a normal named type that implements the interface, there is no (good) way around it.


Now, this post is only, up until here, referring to the bit that the C# compiler and/or .NET will allow you to do. There is another concept in play here as well that, even if the C# compiler allowed you to do this, would make the concept shady.

And that is intent.

An interface does the following:

  • Declare a contract about what implementors has to supply of members
  • Declare a contract about what users can expect of members to be available
  • Declare a contract about the meaning of those members

This last part is hard to impose onto a type even if you could thread an interface over its head. If I write a class that just happens to have the same members that one of your interfaces, if you were to thread that interface onto my class, could you impose the same meaning of those members?

No, you can't.


Now, obviously, there are ways around it but none that are easy and I would say that in most cases they would be hacks that hide poor design.

In any case, to circumvent this you could, via reflection, build up another type that simultaneously wraps and delegates all members to the type of your object, as well as implement this interface, at runtime.

Is it good design? No, definitely not.

If you really want to go down this route you can, as commented below, use the "ImpromptuInterface" nuget package, and your code would then look like this:

var entity = new { FileMasterId = fileMasterId }.ActLike<IHasFiles>();

But I would strongly advice against this. Declare the type!