ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 간단한 디펜던시 인젝션(DI) 구현
    프로그래밍/기록, 개념, 용어 2022. 11. 14. 14:21
    반응형

    Singleton, Transient, Scoped 같은 라이프타임은 제외하고, 어떻게 생성자가 요구하는 인자들을 순서대로 전달하는지에 대해 초점을 맞췄습니다.

     

    아래에 HelloService가 있습니다.

    HelloService 클래스는 생성자에서 string과 List<string>을 파라미터로 가지고 있습니다.

    우리는 이 HelloService를 생성할 때, 외부에서 지정한 인자들을 주입하는 것이 목적입니다.

    class HelloService
    {
        private string _header;
        private List<string> _contents;
    
        public HelloService(string header, List<string> contents)
        {
            _header = header;
            _contents = contents;
        }
    
        public void Hello()
        {
            Console.WriteLine(_header);
            
            foreach (string content in _contents)
            {
                Console.WriteLine(content);
            }
        }
    }

     

    먼저 HelloService의 생성자와, 생성자 파라미터 정보를 가져오는 방법은 아래와 같습니다.

    // 생성자 정보를 가져옴.
    ConstruectorInfo? ctorInfo = typeof(HelloService).GetConstructors().Single();
    
    // 생성자 파라미터 정보를 가져옴.
    ParameterInfo[]? paramInfos = ctorInfo.GetParameters();
    
    // 생성자 파라미터 정보에서 파라미터 타입들을 가져옴.
    Type[] paramTypes = paramInfos.Select(pi => pi.ParameterType).ToArray();

     

    그리고 특정 타입의 인스턴스를 만드는 방법은 아래와 같습니다.

    Type helloServiceType = typeof(HelloService);
    object[] ctorArgs = new object[]{};
    
    object helloServiceInstance = Activator.CreateInstance(helloServiceType, ctorArgs);

     

    그리고 디펜던시 인젝션에 사용될 ServiceCollection은 아래와 같습니다.

    이 클래스의 기능은 타입과, 타입의 인스턴스 저장하고, 가져오는 것 밖에 없습니다.

    public class ServiceCollection
    {
        Dictionary<Type, object?> _items = new();
    
        public void AddSingleton<T>(T item)
        {
            _items.Add(typeof(T), item);
        }
    
        public object GetSingleton(Type type)
        {
            return _items[type]!;
        }
    }

     

    위 요소들로 디펜던시 인젝션을 활용한 인스턴스 생성하는 코드입니다.

    using System.Reflection;
    using System.Collections.Generic;
    using System.Linq;
    using System;
    
    class HelloService
    {
        private string _header;
        private List<string> _contents;
    
        public HelloService(string header, List<string> contents)
        {
            _header = header;
            _contents = contents;
        }
    
        public void Hello()
        {
            Console.WriteLine(_header);
    
            foreach (string content in _contents)
            {
                Console.WriteLine(content);
            }
        }
    }
    
    public class ServiceCollection
    {
        Dictionary<Type, object?> _items = new();
    
        public void AddSingleton<T>(T item)
        {
            _items.Add(typeof(T), item);
        }
    
        public object GetSingleton(Type type)
        {
            return _items[type]!;
        }
    }
    
    static class Program
    {
        public static void Main(string[] _)
        {
            ServiceCollection collection = new ();
    
            collection.AddSingleton("header");
            collection.AddSingleton(new List<string>()
            {
                "hello",
                "world",
                "!"
            });
    
            // 생성자 정보를 가져옴.
            ConstructorInfo ctorInfo = typeof(HelloService).GetConstructors().Single();
    
            // 생성자 파라미터 정보를 가져옴.
            ParameterInfo[]? paramInfos = ctorInfo.GetParameters();
    
            // 생성자 파라미터의 타입들을 가져옴.
            IEnumerable<Type> paramTypes = ctorInfo
                .GetParameters()
                .Select(paramInfo => paramInfo.ParameterType);
    
            object[] ctorArgs = paramTypes.Select(collection.GetSingleton).ToArray();
    
            HelloService helloService = (HelloService)Activator.CreateInstance(typeof(HelloService), ctorArgs)!;
    
            helloService.Hello();
        }
    }

    결과

    helloService.Hello()

    반응형
Designed by Tistory.