Monday, October 26, 2020

Explicit Project References

We have a background processor task that launches different processes using reflection. When debugging this, I will modify some code and then run a test. The modified code is not executed. This is because Visual Studio does not realize it needs to rebuild the modified code.

Visual Studio maintains a Dependency Tree based on the dependencies you specify for each project. If code in A instantiates code in B you have to specify a dependency. If you don't do this then the project won't build.


When you set the startup project(s) for the solution and hit Build, Visual Studio looks at the dependency tree for all the startup project(s) and rebuilds any that are out of date. This works well until we start using Reflection or Process.Start. 

Before we go any further, be aware that, in .Net Core, GetType from another assembly will not work unless that assembly has been explicitly loaded. This is a change from .Net Framework. 

Start a new .Net Core console app in Visual Studio and call it ReferenceTree. Add a .Net Core class library project called Dependency and rename Class1 to Dependency. Your solution explorer looks like this.


The Dependency project does something trivial.

namespace Dependency
{
    public class Something
    {
        public string DoSomethingAndReturnData()
        {
            return "Data";
        }
    }
}

The progam.cs will call this through reflection. Please feel free to alter the Assembly.Load as desired. The important thing to see here is that there is no explicit reference to the Dependency class.

 using System;

using System.Reflection;
namespace ReferenceTree
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom(@"C:\Users\Terry\source\repos\ReferenceTree\Dependency\bin\Debug\netcoreapp3.1\Dependency.dll");
            Type type = Type.GetType("Dependency.Something,Dependency");
            object o = Activator.CreateInstance(type);
            MethodInfo method = type.GetMethod("DoSomethingAndReturnData");
            Console.WriteLine(method.Invoke(o,null));
        }
    }
}

Run the program and you will see a console window like this.


Now go to the Something class and change "Data" to "DataX" and hit F5 to run the program again. You still see "Data" because Visual Studio doesn't know it needs to rebuild Dependency.dll.

Put a breakpoint on the return statement in the Something class and hit F5 again. It doesn't even hit your breakpoint, does it?

All you have to do is right-click on Dependencies in the ReferenceTree project in Solution Explorer and select Add Project Reference. You'll see the checkbox next to Dependency is unchecked because we don't have an explicit reference. Check the box.


Now hit F5 again. You will see the Dependency project being built before the console window opens with the correct value. If your breakpoint is still there, it will hit that on the way.



The takeaway from this blog entry is that you can use the Project References to allow your code to reference other projects and also to tell Visual Studio that you are referencing projects indirectly and they need to be included in the dependency tree.



No comments:

Post a Comment