C#에서의 제네릭 기반 서비스 주입 패턴

제네릭 인터페이스 팩토리 패턴

인터페이스와 구현체를 매핑하여 단일 인스턴스를 관리하는 방식입니다.


public class ServiceFactory<TInterface, TImplementation>
    where TInterface : class
    where TImplementation : TInterface
{
    private static TInterface instance;

    public static TInterface Instance
    {
        get
        {
            if (instance == null)
            {
                instance = Activator.CreateInstance<TImplementation>();
            }
            return instance;
        }
    }
}

사용 예시


ServiceFactory<IMessageService, EmailService>.Instance.SendMessage();

제네릭 싱글톤 팩토리

지정된 타입에 대해 정적 인스턴스를 생성하고 재사용합니다.


public class SingletonFactory<T> where T : class, new()
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = Activator.CreateInstance<T>();
            }
            return instance;
        }
    }
}

사용 예시


SingletonFactory<EmailService>.Instance.SendMessage();

동적 서비스 매핑 시스템 (신규)

사용자 클래스, 인터페이스, 구현 클래스 간의 연결을 런타임에 등록 및 해결합니다.


public class DynamicServiceResolver
{
    private static readonly Dictionary registry = new();
    private static readonly HashSet<string> uniqueKeys = new();

    private static DynamicServiceResolver instance;
    public static DynamicServiceResolver Instance => instance ??= new();

    private DynamicServiceResolver() { }

    public void Register<TUser, TInterface, TImpl>()
    {
        var key = $"User:{typeof(TUser).Name},Interface:{typeof(TInterface).Name},Impl:{typeof(TImpl).Name}";
        if (uniqueKeys.Contains(key)) return;

        uniqueKeys.Add(key);
        registry[typeof(TUser)] = (typeof(TInterface), typeof(TImpl));
    }

    public TInterface Resolve<TUser, TInterface>()
    {
        if (!registry.TryGetValue(typeof(TUser), out var mapping))
            throw new InvalidOperationException("등록된 서비스가 없습니다.");

        if (mapping.InterfaceType != typeof(TInterface))
            throw new InvalidOperationException("인터페이스 유형이 일치하지 않습니다.");

        try
        {
            return (TInterface)Activator.CreateInstance(mapping.ImplementationType);
        }
        catch
        {
            throw new InvalidOperationException($"구현 클래스 {mapping.ImplementationType.Name}는 공개 생성자가 필요합니다.");
        }
    }
}

예제: 메시지 및 음악 서비스 정의


public interface IMessageService
{
    void SendMessage();
}

public interface IMusicService
{
    void SendMessage();
}

public class EmailService : IMessageService
{
    public void SendMessage() => Console.WriteLine("이메일 전송 중...");
}

public class SMSService : IMessageService
{
    public void SendMessage() => Console.WriteLine("SMS 전송 중...");
}

public class PhoneCallService : IMusicService
{
    public void SendMessage() => Console.WriteLine("음성 통화 전송 중...");
}

서비스 등록 코드


static void InitializeServices()
{
    DynamicServiceResolver.Instance.Register<NotificationAndroid, IMessageService, EmailService>();
    DynamicServiceResolver.Instance.Register<NotificationWeb, IMessageService, SMSService>();
    DynamicServiceResolver.Instance.Register<NotificationIOS, IMusicService, PhoneCallService>();
}

실행 예시


static void Main(string[] args)
{
    InitializeServices();

    DynamicServiceResolver.Instance.Resolve<NotificationAndroid, IMessageService>().SendMessage();
    DynamicServiceResolver.Instance.Resolve<NotificationWeb, IMessageService>().SendMessage();
    DynamicServiceResolver.Instance.Resolve<NotificationIOS, IMusicService>().SendMessage();

    Console.ReadKey();
}

태그: 제네릭 C# 서비스 주입 싱글톤 팩토리 패턴

6월 28일 18:21에 게시됨