在什么情况下,GetType()方法将返回接口的类型

时间:2014-09-29 02:03:10

标签: c#

我问这个是因为我得到了一个由WCF运行时生成的对象,并且在其上调用GetType()会返回一个接口类型。因此,如果您对WCF不熟悉或不感兴趣,这是更具体的问题。

这是我问的相关问题: why an object of WCF service contract interface can be casted to IClientChannel

1 个答案:

答案 0 :(得分:1)

我无法对可能发生这种情况的所有案例进行编目,但这里有一些关于此特定情况的信息。 CLR有一些工具可以在System.Runtime.Remoting中拦截调用。特别是班级RealProxy似乎很特别。您可以使用它包装对象并拦截对对象的方法的调用。此article有许多有关如何使用/实施RealProxy的详细信息。我发现你可以用它来拦截像GetType这样的方法。我怀疑WCF在动态生成的类中也是如此。使用该文章中的一些示例演示:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(new DynamicProxy(new Calculator(), typeof(ICalculator)).GetTransparentProxy().GetType());
    }
}

public interface ICalculator
{
    double Add(double x, double y);
}

class Calculator : ICalculator
{
    public double Add(double x, double y)
    {
        throw new NotImplementedException();
    }
}

class DynamicProxy : RealProxy
{
    private readonly object _decorated;
    private readonly Type _reportedType;
    private static readonly MethodInfo GetTypeMethodInfo = typeof(object).GetMethod("GetType");

    public DynamicProxy(object decorated, Type reportedType)
        : base(reportedType)
    {
        _decorated = decorated;
        _reportedType = reportedType;
    }

    private void Log(string msg, object arg = null)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(msg, arg);
        Console.ResetColor();
    }

    public override IMessage Invoke(IMessage msg)
    {
        var methodCall = msg as IMethodCallMessage;
        var methodInfo = methodCall.MethodBase as MethodInfo;
        Log("In Dynamic Proxy - Before executing '{0}'",
          methodCall.MethodName);
        try
        {
            object result;
            if (GetTypeMethodInfo.Equals(methodInfo))
            {
                result = _reportedType;
            }
            else
            {
                result = methodInfo.Invoke(_decorated, methodCall.InArgs);
            }

            Log("In Dynamic Proxy - After executing '{0}' ",
              methodCall.MethodName);
            return new ReturnMessage(result, null, 0,
              methodCall.LogicalCallContext, methodCall);
        }
        catch (Exception e)
        {
            Log(string.Format(
              "In Dynamic Proxy- Exception {0} executing '{1}'", e),
              methodCall.MethodName);
            return new ReturnMessage(e, methodCall);
        }
    }
}