c# - 意想不到的系统.__带有反射的佳能

标签 c# .net clr

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

场景
Windows Server 2008 R2 标准版,64 位
Microsoft .NET Framework 版本:2.0.50727.4927
ASP.NET 版本:2.0.50727.4927
以集成管道模式运行的IIS应用程序池。
安装 .NET Framework 4.0。

这些是一些压缩示例,用于显示出现此问题的代码流。我删除了很多日志记录、契约(Contract)等,只是为了让这篇文章的代码简短。

// 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,文化=中性,PublicKeyToken=b77a5c561934e089]]"
  • type.UnderlyingSystemType = "IRepositoryWithTypedId`2[System.__Canon,System.Guid]"
  • type.GenericArguments[0] = typeof(__Canon)

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

有什么想法或想法吗?

最佳答案

差异可能是由于调试版本与发布版本造成的吗?这里有个好read关于为什么这会出现在发布版本和 here 中是可供您使用的不同优化开关。听起来像是一个似是而非的解释,尤其是当问题与最近的更改无关时。

关于c# - 意想不到的系统.__带有反射的佳能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3108362/

相关文章:

.net - 如何在 C++ 上从 CLR 捕获事件

c# - 命令的执行需要一个开放且可用的连接。连接的当前状态已断开。

c# - 如何让Visual Studio 2010 + 2012 + 2013共存?

c# - 在 C# 中从 xlsx 文件获取记录时出错

.net - 日志中的 BinarySecurityToken

c# - 时间序列趋势数据的重采样、聚合和插值

c# - 如何在ListView中选择项目?

c# - 我们可以在 DotNet 类库项目中使用 global.asax 文件吗

使用反射在运行时进行 C# 类型转换

java - 反射运行时性能 - Java 与 CLR