Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't see class-level variables when debugging in Visual Studio 2013

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.

enter image description here

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.

enter image description here

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.

like image 443
Bob Horn Avatar asked Mar 07 '14 17:03

Bob Horn


People also ask

How do I show variables in Debug in Visual Studio?

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.

How do I view variables in Visual Studio?

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.

Which of the following Windows displays the variables while debugging?

The Autos and Locals windows show variable values while you are debugging. The windows are only available during a debugging session.


1 Answers

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:

enter image description here

Now create a proxy for the object. enter image description here

Notice I hover over the instance to show it is a transparent proxy.

Now hover over the Name property of the transparent proxy instance. enter image description here

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.

enter image description here

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);
        } 
    }
}
like image 158
Jim Avatar answered Oct 29 '22 08:10

Jim