I'm observing some odd behavior while debugging some C# code in VS 2013. When I hover over any variables scoped to the current method, I can see the variable's information. In the screenshot below, you can see that ivSimulation is pinned and showing information. However, even though you can't tell, I had the mouse over this._simulator
and nothing shows up. QuickWatch shows nothing either.
Another coworker is also having this same issue. We've tried wiping our folders clean and getting the latest again. And we've also tried changing a setting in VS (Tools -> Options -> Debugging -> General -> Use Managed Compatibility Mode) to being checked, but that hasn't worked either. Apparently that has worked for others. This was working just fine in VS 2012.
Any ideas? How can I get the class-level variables to show in the debugger?
Edit: Another piece of the puzzle
If I hover over this
I see that it is a transparent proxy. Not sure why that would happen.
Another piece:
this
refers to a class that derives from ContextBoundObject
. We do that so we can use interception for logging and exception handling. Perhaps that is the reason.
And I was wrong; this isn't working in VS2012. Perhaps I just never noticed it before.
If I try to display the value in the immediate window, this is what I get:
? this._coater.Equipment.Line.Unit.Plant.Site.SiteId Cannot obtain fields or call methods on the instance of type 'Company.Mes.Core.Components.Logic.ModuleDerating.StandardDeratingComponentLogic' because it is a proxy to a remote object.
Hover over a variable to see its value. When stopped in the debugger hover the mouse cursor over the variable you want to look at. The DataTip will appear showing you the value of that variable. If the variable is an object, you can expand the object by clicking on the arrow to see the elements of that object.
If you want to continue to watch a variable, you can add it to a Watch window from a data tip. Right-click the variable in the data tip, and select Add Watch. The variable appears in the Watch window. If your Visual Studio edition supports more than one Watch window, the variable appears in Watch 1.
The Autos and Locals windows show variable values while you are debugging. The windows are only available during a debugging session.
It is because the this
is a transparent proxy.
The following screenshots demonstrate this issue given the sample code at the bottom.
First creating the real object and hovering over that instance's Name
property:
Now create a proxy for the object.
Notice I hover over the instance to show it is a transparent proxy.
Now hover over the Name
property of the transparent proxy instance.
Nothing shows up! The transparent proxy does a clever marshaling of the calls to the underlying object but the IDE clearly isn't able to figure it out since the returned proxy object is a dynamically generated class based on the Foo
class.
And the output for completeness.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Text;
namespace ConsoleApplication27
{
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo(){ Name = "My Foo1" };
Console.WriteLine(foo.Name);
FooProxy fooProxy = new FooProxy(foo);
Foo proxiedFoo = (Foo)fooProxy.GetTransparentProxy();
Console.WriteLine(proxiedFoo.Name);
}
}
public class Foo : MarshalByRefObject
{
public string Name { get; set; }
}
public class FooProxy
: RealProxy
{
private Foo _target;
public FooProxy(Foo target) : base(typeof(Foo))
{
this._target = target;
}
public override IMessage Invoke(IMessage msg)
{
return InvokeRemoteCall((IMethodCallMessage)msg, this._target);
}
/// <summary>
/// Invokes the remote call.
/// </summary>
/// <param name="methodCall">The method call.</param>
/// <param name="target">The target.</param>
/// <returns>A <see cref="ReturnMessage"/></returns>
private static IMessage InvokeRemoteCall(IMethodCallMessage methodCall, object target)
{
MethodInfo method = methodCall.MethodBase as MethodInfo;
object callResult = (target != null) ? method.Invoke(target, methodCall.InArgs) : null;
LogicalCallContext context = methodCall.LogicalCallContext;
var query = method.GetParameters().Where(param => ((ParameterInfo)param).IsOut);
ParameterInfo[] outParameters = query.ToArray();
return new ReturnMessage(callResult, outParameters, outParameters.Count(), context, methodCall);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With