0

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?


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)

4

1 回答 1

0

问题似乎与从IEnumerable< object >to IEnumerable< string >(或任何类型)转换有关。我通过将枚举器逻辑包装在实现的自定义类中来解决它IEnumerable<T>

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

然后在我的拦截器代码中,我使用反射来实例化 InvocationInfo 对象中指定的正确泛型类型:

  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...
       }
   }

现在,当我进行返回的方法调用时,我的接口的代理对象不再抛出无效的强制转换异常IEnumerable<>

更多关于在这里编写 LinFu 动态代理拦截器

于 2012-06-04T11:40:01.250 回答