An ADR Visual Studio Extension – Dependency Injection
Tags: visualstudio, csharp, extensions
Published: 2020-01-11 14:23:38

<a href="https://www.pmichaels.net/2020/01/04/an-adr-visual-studio-tool-part-3-listing-and-reading-the-files/">Continuing</a> 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 <a href="https://github.com/pcmichaels/ADRManager">here</a>.

<h1>Unity</h1>

In <a href="https://www.pmichaels.net/2018/02/04/using-unity-azure-functions/">this</a> 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 <em>to</em> Visual Studio.

Let's start by installing Unity in our project:

```
Install-Package Unity
```

<h1>Rules Analyser</h1>

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:

```csharp
    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.

<h1>AdrPackage</h1>

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

```csharp
    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;
        }

        . . .
```


<h1>View Model</h1>

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

```csharp
        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.


<h1>References</h1>

<a href="https://stackoverflow.com/questions/2875429/iunitycontainer-resolvet-throws-error-claiming-it-cannot-be-used-with-type-par">https://stackoverflow.com/questions/2875429/iunitycontainer-resolvet-throws-error-claiming-it-cannot-be-used-with-type-par</a>

<a href="https://www.pmichaels.net/2018/02/04/using-unity-azure-functions/">https://www.pmichaels.net/2018/02/04/using-unity-azure-functions/</a>