.NET Inside Out Part 6 — Proxy handling casting in C#

This is the sixth part of the .NET Inside Out series. For your convenience you can find other parts in the table of contents in Part 1 – Virtual and non-virtual calls in C#

Let’s start with the following code:

When we run this we get:

We have interface and one implementer. Also, we have a service which knows internal details of class implementing the interface. This might look suspicious but imagine the following situation: IHaveASandwich interface is in some kind of library which uses only stuff defined in the interface. However, Service is a concrete client of the library which needs to store some additional details required for implementation (e.g., serialization stuff). Client works with IHaveASandwich most of the time, but sometimes it needs to access implementation details so it casts the object to the specific type.

Now, let’s try to write a proxy for that interface, e.g., to add operator overloading:

And the output is:

So, wrapping works, adding works (via operator +), but now it fails when casting IHaveASandwichWrappper to ASandwichProvider. Can we fix this?

Well, we can. But it is not that easy. If you try to google this stuff you will find out that it is impossible to overwrite casting operator from and to interface (see Eric Lippert’s answers on SO: here and especially here). So what can we do?

Implementation

First, we need to introduce yet another interface:

Now we cast to interface instead of casting to concrete implementation.
Next, our wrapper needs to be proxy with implemented interface, for which we can use Castle.DynamicProxy (I use package Castle.Core 4.1.1):

We create proxy class implementing all additional interfaces (beside IHaveASandwich) but still treat it as a wrapper. Now our code works:

So now library can give us operators (or any other extension which need to be implemented directly on class, not on interface) and we still can work with internal implementation of our class despite the fact that we get the wrapper instead of our class (which are in different inheritance hierarchy).