Search code examples
c#interfaceienumerablelinfu-dynamicproxy

Linfu dynamic proxy and Interface methods that return IEnumerable<object>


I am using Linfu to generate a proxy object for an interface. Everything works fine except when calling a method that returns an IEnumerable<object> I get an error something like this:

Unable to cast object of type '< IEnumerableRpcCall >d__2' to type 'System.Collections.Generic.IEnumerable`1[System.String]'.

FYI: IEnumerableRpcCall is the name of the method inside the interceptor code that does yield return object rather than return object.

It seems the problem is that linfu is returning a pointer to the method rather than an IEnumerable. Has anyone found a workaround for this?


Solution

  • The problem seems to be related to casting up from IEnumerable< object > to IEnumerable< string > (or whatever type). I solved it by wrapping my enumerator logic inside a custom class that implements IEnumerable<T>:

      public class MyEnumerator<T> : IEnumerable<T>, IEnumerable
      {
            // custom logic here
      }
    

    and then in my interceptor code I use reflection to instantiate the correct generic type as specified in the InvocationInfo object:

      private class MyLinfuInterceptor : IInterceptor
      {
          public object Intercept(InvocationInfo info)
          {
                MethodInfo methodBeingRequested = info.TargetMethod;
                // enumerable return type
                if (methodBeingRequested.ReturnType.IsGenericType
                   && methodBeingRequested.ReturnType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
                   && methodBeingRequested.ReturnType.GetGenericArguments().Length == 1)
                {
                   Type constructedEnumerator = typeof(MyEnumerator<>).MakeGenericType(methodBeingRequested.ReturnType.GetGenericArguments());
                   var result = Activator.CreateInstance(constructedEnumerator);
    
                   return result;
                }
    
                // code to handle other return types here...
           }
       }
    

    And now the proxy object for my interface no longer throws an invalid cast exception when I make method calls that return IEnumerable<>

    (more on writing LinFu Dynamic Proxy interceptors here)