Tag Archives: Visual Studio

An ADR Visual Studio Tool – Part 4 – Dependency Injection

Continuing with my little series on creating a visual studio extension, in this post, I’ll talk about how to add dependency injection to your project.

If you’d like to see the whole solution for this, it can be found here.

Unity

In this post on Azure Functions, I talked about using Unity as an IoC container, in a place where an IoC container might not necessarily fit; whilst this is no longer true for Azure functions, it does appear to be for extensions – I presume because they don’t expect you to have one big enough to warrant IoC; also, even with DI, testing is very difficult, because most of what you’re doing, you’re doing to Visual Studio.

Let’s start by installing Unity in our project:

Install-Package Unity

Rules Analyser

In our case, we were analysing the project and extracting files; however, we were extracting all files; as a result, a check needed to be made to extract only markdown files. Consequently, I created a RulesAnalyser class:

    public class RulesAnalyser : IRulesAnalyser
    {
        public bool IsProjectItemNameValid(string projectItemName) =>
            projectItemName.EndsWith("md");        
    }

We could (and I did initially) instantiate that directly in the ViewModel, but that feels quite dirty.

AdrPackage

The *Package file for the extension seems to be the entry point, so we can add the unity container to here:

    public sealed class AdrPackage : AsyncPackage
    {        
        public static Lazy<IUnityContainer> UnityContainer =
         new Lazy<IUnityContainer>(() =>
         {
             IUnityContainer container = InitialiseUnityContainer();
             return container;
         });

        private static IUnityContainer InitialiseUnityContainer()
        {
            UnityContainer container = new UnityContainer();
            container.RegisterType<IRulesAnalyser, RulesAnalyser>();
            container.RegisterType<ISolutionAnalyser, SolutionAnalyser>();
            return container;
        }

        . . .

View Model

The next thing we need to do is to inject our dependencies.

        public AdrControlViewModel() 
            : this(AdrPackage.UnityContainer.Value.Resolve<IRulesAnalyser>(),
                  AdrPackage.UnityContainer.Value.Resolve<ISolutionAnalyser>())
        {}

        public AdrControlViewModel(IRulesAnalyser rulesAnalyser, ISolutionAnalyser solutionAnalyser)
        {            
            _rulesAnalyser = rulesAnalyser;
            _solutionAnalyser = solutionAnalyser;

            Scan = new RelayCommandAsync<object>(ScanCommand);
        }

And that’s it, we now have a working DI model in our project.

References

https://stackoverflow.com/questions/2875429/iunitycontainer-resolvet-throws-error-claiming-it-cannot-be-used-with-type-par

https://www.pmichaels.net/2018/02/04/using-unity-azure-functions/

An ADR Visual Studio Tool – Part 3 – Listing and Reading the files

In this post, I refactored a VS Extension Plug-in, that I originally started here.

We’ll get the plug-in to list the items found in the projects, and read the contents of the files. The source code for this can be found here. I won’t be listing all the source code in this article (most of it is just simple WPF and View Model binding).

To look through all the projects and folders in the solution, we’ll need to recursively scan all the files, and then read them; let’s have a look at what such a method might look like:

        private async Task ScanProjectItems(ProjectItems projectItems, ProjectData projectData)
        {
            await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            foreach (EnvDTE.ProjectItem pi in projectItems)
            {
                if (pi.IsKind(ProjectItemTypes.SOLUTION_FOLDER, 
                              ProjectItemTypes.PROJECT_FOLDER,
                              ProjectItemTypes.SOLUTION_ITEM)
                    && pi.ProjectItems != null)
                {                    
                    await ScanProjectItems(pi.ProjectItems, projectData);
                    return;
                }

                string text = await GetDocumentText(pi);
                if (string.IsNullOrWhiteSpace(text)) continue;

                projectData.Items.Add(new Models.ProjectItem()
                {
                    Name = pi.Name,
                    Data = text
                });
            }
        }

I wanted to look specifically into two aspects of this method: IsKind() and GetDocumentText(). None of the rest of this is particularly exciting.

Kind of File

In a VS Extension, you can read ProjectItems – they represent pretty much anything in the solution, and so it’s necessary to be able to find out exactly what the type is. As you can see above, I have an extension method, which was taken from here. Let’s have a quick look at the file that defines the ProjectItemTypes:

    public static class ProjectItemTypes
    {
        public const string MISC = "{66A2671D-8FB5-11D2-AA7E-00C04F688DDE}";
        public const string SOLUTION_FOLDER = "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}";
        public const string SOLUTION_ITEM = "{66A26722-8FB5-11D2-AA7E-00C04F688DDE}";                                            
        public const string PROJECT_FOLDER = "{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}";        
    }

I’m sure there’s a better way, but after I realised what Mads was doing in the above linked project, I just stuck a breakpoint in the code, and copied the “Kind” guid from there! The IsKind method is taken from the same codebase:

        public static bool IsKind(this ProjectItem projectItem, params string[] kindGuids)
        {
            Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

            foreach (var guid in kindGuids)
            {
                if (projectItem.Kind.Equals(guid, StringComparison.OrdinalIgnoreCase))
                    return true;
            }

            return false;
        }

As you can see, it’s almost not worth mentioning – except that the extensions are very particular about running in the UI thread, so you’ll find ThrowIfNotOnUIThread scattered around your code like confetti!

Reading File Contents

If you need to access the file contents in an extension, one way is to convert the project item document to a TextDocument, and then use Edit Points:

        public static async Task<string> GetDocumentText(this ProjectItem projectItem)
        {
            if (projectItem == null) return string.Empty;
            await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            try
            {
                TextDocument textDocument;
                if (!projectItem.IsOpen)
                {
                    var doc = projectItem.Open(EnvDTE.Constants.vsViewKindCode);
                    textDocument = (TextDocument)doc.Document.Object("TextDocument");
                }
                else
                {
                    textDocument = (TextDocument)projectItem.Document.Object("TextDocument");
                }
                EditPoint editPoint = textDocument.StartPoint.CreateEditPoint();
                return editPoint.GetText(textDocument.EndPoint);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

Edit Point are much more powerful that this, they allow you to change the text in a document; for example, imagine your extension needed to change every local pascal cased variable into one with an underscore (myVariable to _myVariable), you may choose to use edit points there.

References

https://www.csharpcodi.com/csharp-examples/EnvDTE.Document.Object(string)/

https://github.com/madskristensen/MarkdownEditor/

.Net Client Side Libraries

In this post, I introduced (to me) a new method of installing client side Javascript libraries for a .Net Web Application.

In this follow-up, I’m going to cover how this can be used in conjunction with npm in order to simply move the files into the correct location. Note that this is a new tool in Visual Studio, and you’ll need VS 15.8.0 or higher for it to work. Let’s start by creating an empty .Net Core Web App. Once you’ve done so, you’re app probably looks like this:

Now you’ll need to launch a bash or powershell console:

npm init
npm install jquery

Refresh your project and show all files:

As you can see, you now have a node_modules directory. The problem is that the files need to be under wwwroot. Obviously, you could copy it, but let’s try the client side manager:

In the resultant dialog, select File System; navigate to the JQuery directory and select the files that you want:

Now refresh the project again and let’s see what we have:

This actually translates to a JSON file; libman.json looks like this:

{
  "version": "1.0",
  "defaultProvider": "filesystem",
  "libraries": [
    {
      "library": "node_modules\\jquery\\dist\\",
      "destination": "wwwroot/lib/dist/",
      "files": [
        "jquery.min.js"
      ]
    }
  ]
}

Abusing the system

Okay – so that’s very nice; but now that we have a system that will copy files from wherever into wherever (the rule is that you have to go deeper in the files structure – so you couldn’t copy that file back again) then we, presumably, could use this for other things. For example, have you ever had a file (an image or something) that you need to include in your project:

Obviously, c:\tmp above could just as easily be \\shareddrive\images.

To be clear, I’m unsure whether this is abusing the system, or it was meant for this exact thing. It is possible that this type of usage may become unsupported in future (so you’ve been warned).

Live Testing in Visual Studio 2017

While working on this project, I decided that I would see how useful the new feature of “Live Testing” is for TDD.

Once you’ve created your suite of tests, turning live testing on gives you some interesting information:

As you can see, there are some slight contradictions here in what it’s telling me. The first test is failing, the test for Count has a line (which indicates not covered). However, code lens is telling me there are two covering tests.

My suspicion here is that live testing is being too clever for its own good; for example, looking at the tests themselves, shows that only the first Enqueue statement is covered:

My thoughts are that the engine works out where the test fails, and so, in the case above, it’s telling me that the tests are not running the line of code that tests the Count functionality. What I’m guessing is that this is because the tests are failing before that.

I can prove this by creating a further unit test:

And, indeed, this now shows coverage:

As I start to add the functionality, I can quickly see that the tests are now passing:

Changing the way code is written

The interesting thing here is that is promotes two things:
1. Defined tests – if a test covers more than one thing, it will show as uncovered initially
2. Tests first – obviously, there need to be tests to show test coverage

Caveats

1. Annoyingly, by default, you continually have to opt in for live unit testing. It only starts when you select to “Start” live unit testing, and this must be done each time you launch VS. This is configurable, and can be switched on by default in options:

2. If the build fails, it shows nothing.

3. Live testing is only available in Visual Studio Enterprise.

NUnit

One thing that only occurred to me as notable while I was writing this is that the tests that I’ve written are in NUnit. So the Live Testing clearly works with none MSTests, and probably works with anything that’ll show up in Test Explorer / Code Lens.

References

https://blogs.msdn.microsoft.com/visualstudio/2017/03/09/live-unit-testing-in-visual-studio-2017-enterprise/

Convert a standard C# project into a Unit Test project

I recently (accidentally) created a Unit Test project as a standard C# class library. Although you don’t need to change this to a test library (it basically just gives you the test icon instead of the class icon), I felt that, if I wanted to do this, it shouldn’t require that I delete and recreate the project.

To change the project type

If you open the csproj for a class library, it looks like this (or some of it does):

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{93F28F24-AD9B-4839-8697-6DA48BAB2048}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>MyProject.UnitTests</RootNamespace>
    <AssemblyName>MyProject.UnitTests</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>

All you need to do is add the correct ProjectTypeGuids:

<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

References

https://www.codeproject.com/Reference/720512/List-of-Visual-Studio-Project-Type-GUIDs

http://stackoverflow.com/questions/2911565/what-is-the-significance-of-projecttypeguids-tag-in-the-visual-studio-project-fi

Start Two Project Simultaneously

In Investigating message queues with RabbitMQ and ActiveMQ, I came across a problem that I’ve never considered before. Starting two projects at the same time.

The well-known (at least to me) way of doing this was to start the start-up project, and then right-click the second project, and select Start New Instance:

2proj

However, this is laborious when you’re constantly starting both projects. So, the alternative is to right click the solution, and select Set StartUp Projects… :

2proj2

Then you can select to start multiple projects:

2proj3

A small thing, but saves a lot of time.

The “GenerateResource” task failed unexpectedly

I recently started getting this error on a solution:

GenerateResource

It didn’t actually report any errors, other than this and, no matter what I tried (deleting the suo file, rebuilding, cleaning, etc.), it wouldn’t go away.

Finally, I ran up a command prompt and tried to compile it there. I immediately got this error:

MyViewModel.cs(63,28): error CS1056: Unexpected character ‘$’ [C:\Users\Paul\Desktop\MyApp\MyApp\kqlonrzo.tmp_proj]

Okay, so, the project definitely did use the new $ character. Here’s the thing, whilst I was trying to compile using VS2015, the version of the command prompt that I had run was 2012. The next thing was to try running the command prompt for VS2015.

This gave a less than useful error regarding `MyProject.csproj.metadata` file. So, next I tried compiling the project directly from the command line.

Finally, that worked. Unfortunately, I was unable to break the compile again. However, it isn’t the first time that I’ve encountered this error: hence this post.

So, whilst not proven, for next time, try compiling the solution using the command line and, if that doesn’t work, try compiling the individual project file first.

Now using Visual Studio 14 CTP

I was previously using VS2013, but after running 14 just once, I saw no reason to go back. I thought I’d jot down some notes on my experience of this update. A quick caveat though: VS14 is a CTP, so if you’re thinking about using it to maintain the code for your nuclear reactor, then probably don’t.

Faster

Okay, so this is my perception. I’m working on a personal project on the train to and from work. VS14 loads almost a station before VS2013 did. Now, if that’s not a fair and accurate benchmark, I don’t know what is!

Debugging

One particularly cool feature is that you can see the CPU execution time for previous statement during debugging. Typically, this is a meaninglessly low figure of x milliseconds; but occasionally it shows an unexpectedly high figure.

This can be dangerous, because if you saw a statement that took 30ms, which executed once when the user presses a button in your app, you might think nothing of it… unless all the other statements take 2ms. At this point, you might spend 1/2 hour trying to work out what the bottleneck is. You might even find it: and speed up your app by 28ms.

Refactor

Shift-Alt-F10 on a non-existent method now gives you a preview of what it’s about to do. Possibly not the most useful feature in the world to be honest, but if you want a field and it tries to create a property then you know (obviously, if you’d just read the description of what it will create, that would also tell you). The Using statement tells you where it will create the statement:

preview

However, I can’t find any way you can affect the preview – which would have been a nice feature; for example, say you wanted to create a public field rather than internal; or, you wanted to define a constant and give it a constant value.

Light bulbs now appear next to potential refactoring. One example was an unnecessary using statement I had. It had turned grey; I didn’t understand this until I noticed that a light bulb had appeared next to it, which helpfully informed me that I didn’t need the statement.

Also, code analysis seems to be an opt-in thing now – rather than the previous version which seemed to constantly kidnap whichever tab it was on.

It is still a CTP

Line numbers were turned on in VS2013 and were off in 14.