意外的系统.__佳能与反思

时间:2010-06-24 08:39:21

标签: c# .net clr

击穿
“System.Reflection.TargetException:Object与目标类型不匹配。”在RealProxy的派生中调用MethodBase.Invoke时。在svn提交日志或服务器事件日志中突然出现问题并且没有任何明显的原因。

方案
Windows Server 2008 R2 Standard,64位
Microsoft .NET Framework版本:2.0.50727.4927
ASP.NET版本:2.0.50727.4927
IIS应用程序池以集成管道模式运行 .NET Framework 4.0安装了 NOT

这些是一些压缩样本,用于显示出现此问题的代码流。我已经删除了很多日志记录,合同等,只是为了保持这篇文章的代码简短。

// Interface structure
ICommentRepository : IRepository<Comment>  
IRepository<T> : IRepositoryWithTypedId<T, Guid>  
IRepositoryWithTypedId<T, TId>
    void Delete(T item);

// Extract from ServicesProvider which instantiates the proxies.
public class ServicesProvider {
    public T GetService<T>() where T : class {
        var proxy = WcfProxyFactory<T>.OpenChannel();
        proxy = ApplyLoggingProxy(proxy);
        return proxy;
    }

    private static T ApplyLoggingProxy<T>(T instance) where T : class {
        return (T)new LoggingProxy<T>(instance).GetTransparentProxy();
    }
}

public class LoggingProxy<T> : ProxyBase<T> where T : class {
    public LoggingProxy(T instance)
        : base(instance) {
    }

    protected override IMethodReturnMessage InvokeMethodCall(IMethodCallMessage msg) {
        var methodName = String.Format("{0}.{1}", InstanceType.Name, msg.MethodName);
        // methodName = "ICommentRepository.Delete"

        var methodCall = ReflectionHelper.GetMethodCall(msg);
        // methodCall = "IRepositoryWithTypedId<__Canon, Guid>.Delete(...)"

        Trace.WriteCategory(methodName, "Calling {0}", methodCall);

        return base.InvokeMethodCall(msg);
    }
}

public abstract class ProxyBase<T> : RealProxy where T : class {
    protected static readonly Type InstanceType = typeof(T);
    protected readonly T Instance;
    protected readonly ITraceWriter Trace = new HttpContextTraceWriter();

    protected ProxyBase(T instance) {
        Instance = instance;
    }

    public override IMessage Invoke([NotNull] IMessage msg) {
        var methodCallMessage = msg as IMethodCallMessage;
        if (methodCallMessage != null)
            return InvokeMethodCall(methodCallMessage);

        throw new NotImplementedException("Unknown message type");
    }

    protected virtual IMethodReturnMessage InvokeMethodCall([NotNull] IMethodCallMessage msg) {
        var args = msg.Args;
        var result = msg.MethodBase.Invoke(Instance, args);
        return new ReturnMessage(result, args, msg.ArgCount, msg.LogicalCallContext, msg);
    }
}

// Line causing the error.
servicesProvider.GetService<ICommentRepository>().Delete(...);

亮点
我在LoggingProxy.InvokeMethodCall中添加了一些调试,专门写出了msg.Method(声明为MethodBase,是RuntimeMethodInfo)和msg.Method.DeclaringType的所有属性。我会提供一些奇怪的亮点。

  • method.Attributes =( PrivateScope | Public | Virtual | HideBySig | VtableLayoutMask | Abstract),PrivateScope表示“表示无法引用该成员”。我很确定我有一个参考。 ;)
  • method.DeclaringType =“IRepositoryWithTypedId`2 [ System .__ Canon ,System.Guid]”
  • method.ReflectedType =“IRepositoryWithTypedId`2 [ System .__ Canon ,System.Guid]”
  • type.FullName =“IRepositoryWithTypedId`2 [[ System .__ Canon,mscorlib,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089 ],[System.Guid,mscorlib,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]“
  • type.UnderlyingSystemType =“IRepositoryWithTypedId`2 [ System .__ Canon ,System.Guid]”
  • type.GenericArguments [0] = typeof( __ Canon

我不知道这是怎么发生的,以及如何解决它。一些谷歌搜索提供了禁用内联方法(MethodImplAttribute)的提示,但我无法找到执行此操作的位置。我已经将它们放在所有方法中而无法解决问题。

有什么想法或想法吗?

1 个答案:

答案 0 :(得分:1)

差异可能是由于Debug与Release版本有关吗?这是一个很好的read,为什么这会在版本构建中出现,here是您可以使用的不同优化开关。听起来似乎是一个看似合理的解释,特别是如果问题与最近的变化无关。