C#でDIコンテナを使用してみる

csharp C#

概要

C#でDIコンテナを使用する方法について解説します。

DIコンテナは、MicrosoftのUnityを使用します。

DIコンテナの説明については、割愛します。

環境

本記事では、以下の環境で開発を行いました。

  • Visual Studio 2019
  • .NET Framework 4.6.1
  • コンソールアプリ、クラスライブラリ

DIコンテナのインストール

テスト用のソリューション及びプロジェクトを作成します。

DIContainerTestAppはコンソールアプリ、DITestLibraryはクラスライブラリで作成します。

DITestLibraryに、以下のインターフェースを追加します。

namespace DITestLibrary
{
    public interface IDevice
    {
        string Name
        {
            get;
            set;
        }
        string GetMessage();
    }
}

DITestLibraryに、以下のクラスを追加します。

namespace DITestLibrary
{
    public class Device : IDevice
    {
        public string Name
        {
            get;
            set;
        }
        public string GetMessage()
        {
            return "Called Device GetMessage methods";
        }
    }
}

NuGetよりUnityをインストールします。

また、設定ファイルから依存性注入を行う形式も実施しますので、Unity.Configurationもインストールします。

ここまでで事前準備は完了です。

DIコンテナを使ってみる

インターフェースとクラスの型を登録し、インターフェースを取得する

ここでは、IDeviceとそれを継承したDeviceクラスを登録しておき、インターフェースを指定し取得する方法を記載します。

diContainer.RegisterType<IDevice, Device>();で、IDeviceとDeviceのリレーションを登録します。

IDevice device = diContainer.Resolve<IDevice>();で、DIコンテナにて、Deviceクラスがインスタンス化され、IDeviceのインターフェースの形で取得することができます。これにより、使用する側は、実際のクラスを意識することなく、インターフェースだけを意識すればよいことになります。

using DITestLibrary;
using System;
using Unity;

namespace DIContainerTestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            UnityContainer diContainer = new UnityContainer();

            diContainer.RegisterType<IDevice, Device>();

            IDevice device = diContainer.Resolve<IDevice>();
            Console.WriteLine(device.GetMessage());
            // >> Called Device GetMessage methods
        }
    }
}

シングルトンで登録し、取得する

RegisterTypeにて、TypeLifetime.Singletonを指定します。

これにより、Resolve時に取得するインスタンスをシングルトンとすることができます。

using DITestLibrary;
using Microsoft.Practices.Unity.Configuration;
using System;
using Unity;

namespace DIContainerTestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            UnityContainer diContainer = new UnityContainer();
            diContainer.RegisterType<IDevice, Device>(TypeLifetime.Singleton);

            IDevice deviceA = diContainer.Resolve<IDevice>();
            deviceA.Name = "device name";

            IDevice deviceB = diContainer.Resolve<IDevice>();

            Console.WriteLine(deviceA.Name);
            // >> device name

            Console.WriteLine(deviceB.Name);
            // >> device name
        }
    }
}

設定ファイルでインターフェースとクラスを指定して、依存性注入してみる

設定ファイル(App.config)に、インターフェースとクラスを指定して、依存性注入する方法を紹介します。

App.configに以下の設定をします。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="DITestLibrary" />
<assembly name="DITestLibrary" />

<container>
<register type="IDevice" mapTo="Device" />
</container>
</unity>
</configuration>

Program.csに以下のコードを記載して実行します。

LoadConfigurationメソッドを呼び出すことにより、DIコンテナが設定ファイルを読み込み、RegisiterInstanceを呼び出すことなく、依存性注入をすることができます。

using DITestLibrary;
using Microsoft.Practices.Unity.Configuration;
using System;
using Unity;

namespace DIContainerTestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            UnityContainer diContainer = new UnityContainer();
            diContainer.LoadConfiguration();

            IDevice device = diContainer.Resolve();
            Console.WriteLine(device.GetMessage());
            // >> Called Device GetMessage methods
        }
    }
}

コメント