Casting Dynamic Object and Passing Into UnitOfWork and Repository Pattern. Throws Exception

c#, dynamicobject, expandoobject, repository-pattern, unit-of-work

Solution

This is one of the bugs I reported to Microsoft more than 5 years ago, soon after the `dynamic` was introduced. As far as I know, it is considered of a very low priority on their list, and might never be fixed.

Here are simple repro steps:

using System.Collections;

class C
{
    static void Main()
    {
        object[] array = { };
        IList list = new ArrayList();
        list.CopyTo(array, 0); // Works okay
        dynamic index = 0;
        list.CopyTo(array, index); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.IList' does not contain a definition for 'CopyTo'
    }
}

Here is an explanation of the problem. When a function member (a method or an indexer) is invoked on an expression whose static type is an interface type, and at least one of the arguments to the invocation is of the type `dynamic` (which means the complete member lookup -- type inference -- overload resolution process is postponed until runtime, and becomes a responsibility of the runtime binder rather than the compiler; only a partial set of checks is performed by the compiler based on incomplete type information), and the member being invoked is inherited by the interface from one of its base interfaces (rather than declared in the interface itself), then the runtime binder fails to properly traverse the tree of the base interfaces to find the inherited member, and throws an exception at runtime, reporting that the required member is not found. Note that it is only the runtime binder's fault -- the compiler properly accepted the invocation (but would reject it, if, for example, you made a typo in the method name).

A possible workaround: cast the expression you invoke a member on to the base interface that actually declares the member you are trying to invoke. For example, the program from the repro steps above could be fixed as follows:

using System.Collections;

class C
{
    static void Main()
    {
        object[] array = { };
        IList list = new ArrayList();
        list.CopyTo(array, 0); // Works okay
        dynamic index = 0;
        ((ICollection) list).CopyTo(array, index); // Works okay
    }
}

Or, if possible, get rid of the dynamic dispatch completely by casting the argument(s) of type `dynamic` to the type specified in the invoked member's signature.

using System.Collections;

class C
{
    static void Main()
    {
        object[] array = { };
        IList list = new ArrayList();
        list.CopyTo(array, 0); // Works okay
        dynamic index = 0;
        list.CopyTo(array, (int) index); // Works okay
    }
}

Unfortunately, both workarounds might be not helpful if you really want overload resolution to happen at runtime, and among the possible candidates there are both members declared by the interface, and members inherited by it. You would probably need to invent some ad hoc solution in that case, or significantly refactor your program.

Problem

This is a very specific problem. Not quite sure how to even word it. Basically I am implementing the unit of work and repository pattern, I have a dynamic object that I convert to an int, but if I use `var` it will throw an exception when trying to call the method. I tried to remove all the trivial variables to this problem that I can. For some reason I only see it happen with these two design patterns. The exception I get is `Additional information: 'BlackMagic.ITacoRepo' does not contain a definition for 'DoStuff'` Here is the code: ``` class BlackMagic { static void Main(string[] args) { dynamic obj = new ExpandoObject(); obj.I = 69; UnitOfWork uow = new UnitOfWork(); int i1 = Convert.ToInt32(obj.I); var i2 = Convert.ToInt32(obj.I); if(i1.Equals(i2)) { uow.TacoRepo.DoStuff(i1); // Works fine uow.TacoRepo.DoStuff(i2); // Throws Exception } } } class UnitOfWork { public ITacoRepo TacoRepo { get; set; } public UnitOfWork() { TacoRepo = new TacoRepo(); } } class Repo<T> : IRepo<T> where T : class { public void DoStuff(int i) { } } interface IRepo<T> where T : class { void DoStuff(int i); } class TacoRepo : Repo<Taco>, ITacoRepo { } interface ITacoRepo : IRepo<Taco> { } class Taco { } ``` EDIT: The main question I am trying to find an answer for, is why would the exception get thrown by calling `DoStuff` inside the unit of work (while using the repo) but not get thrown if DoStuff existed in the `BlackMagic` class.

Original source

Related problems