2

I have the following class in a Universal Windows exe project (actual functionality not included).

sealed class DataPage
{
    public DataPage(dynamic page)
    {
        Data = page;
    }

    public dynamic Data { get; private set; }
}

This assembly includes the InternalsVisibleTo attribute so I can unit test internal classes:

[assembly:InternalsVisibleTo("PictureFrame.UnitTests")]

The unit test project (Universal Windows Unit Test project) compiles just fine. The test below however will throw an exception when passing a dynamic object to the DataPage constructor. It does not except when the instance passed is of type object.

[TestMethod]
public void ReproException()
{
    var o = new object();
    var page = new DataPage(o); // this works fine

    var d = (dynamic)o;
    var page1 = new DataPage(d); // this throws exception
}

The exception thrown is: 'PictureFrame.Model.DataPage.DataPage(object)' is inaccessible due to its protection level.

I can of course mark the internal classes public if they interact with dynamic objects but is this something that is expected to work? This is the first time I've used InternalsVisibleTo and dynamic and am a bit surprised by this behavior, but perhaps it is an edge case from the DLR perspective.

(In real life the dynamic object is an ExpandoObject deserialized from json.)

dkackman
  • 15,179
  • 13
  • 69
  • 123
  • FYI: this works fine if you're targeting a regular .NET project, once you add `Microsoft.CSharp` to the unit test project references. So this appears to be a problem specific to the universal runtime. I'm too lazy to check, but I'm willing to bet a small amount of money that the code to call the constructor ultimately occurs in a different assembly (to which `InternalsVisibleTo` doesn't apply). – Jeroen Mostert Oct 07 '15 at 13:33
  • I added the Microsoft.CSharp nuget package and no joy. Looks like the constructor call is happening within the linq expressions assembly: ''Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Linq.Expressions.dll but was not handled in user code' – dkackman Oct 07 '15 at 19:46
  • @JeroenMostert you are right. It does work in a vanilla .net project. A look at the callstack from within the above constructor shows some code from System.Core.dll!System.Dynamic.UpdateDelegates.UpdateAndExecute2(System.Runtime.CompilerServices.CallSite site, System.Type arg0, object arg1) not linq extensions as in the universal example. – dkackman Oct 07 '15 at 21:57
  • You could try (but this is really a shot in the dark) `[assembly:InternalsVisibleTo("System.Core")]`, since that's where the dynamic code generation seems to live. – Jeroen Mostert Oct 07 '15 at 22:02
  • None of [assembly: InternalsVisibleTo("System.Core")] [assembly: InternalsVisibleTo("Microsoft.CSharp")] [assembly: InternalsVisibleTo("System.Dynamic.Runtime")] do the trick. Oh well. I'll write something up on Microsoft connect and move on. – dkackman Oct 08 '15 at 00:08

0 Answers0