Autofac-根据构造函数的参数名称选择实现

时间:2018-08-11 14:42:53

标签: c# .net dependency-injection autofac

假设我有这样的界面:

interface IDateTimeProvider 
{
    DateTime GetNow();
}

和两个实现:

public class DateTimeProvider : IDateTimeProvider 
{
    public DateTime GetNow()
    {
        return DateTime.Now;
    }
}

public class DateTimeUtcProvider : IDateTimeProvider
{
    public DateTime GetNow()
    {
        return DateTime.UtcNow;
    }
}

我使用Autofac将依赖项注入到我的服务中。我的某些服务需要两种实现,而只有一种:

public class ServiceBoth
{
    (...)
    public ServiceBoth(IDateTimeProvider provider, IDateTimeProvider utcProvider)
    {
        (...)
    }
}

public class Service
{
    (...)
    public ServiceBoth(IDateTimeProvider provider)
    {
        (...)
    }
}

public class ServiceUtc
{
    (...)
    public ServiceBoth(IDateTimeProvider utcProvider)
    {
        (...)
    }
}

如您所见,当我想注入“ DateTimeProvider”时,我将名称为“ provider”的参数称为参数,而当我想注入“ DateTimeUtcProvider”时,则将其名称为“ utcProvider”的参数指针。

现在,我想使用Autofac来实现这种依赖注入方案: 1.我有两种接口实现。 2.注入哪个实现取决于构造函数的参数名称。 3.一切都应该在全局范围内实现,我不想为每个使用IDateTimeProvider的服务创建解析机制。

如何?

编辑:正如史蒂文(Steven)在下面的评论中指出的那样,这种方法违反了《里斯科夫替代原理》,因此我决定放弃这种解决方案。但是,如果有人对如何实施此“不良解决方案”有任何想法,请随时分享。

1 个答案:

答案 0 :(得分:0)

我认为,Autofac无法识别参数名称,但是您可以定义第二个接口,该接口继承自IDateTimeProvider并且还包含GetNow()

public interface IDateTimeProvider
{
    DateTime GetNow();
}

public interface IDateTimeUtcProvider : IDateTimeProvider
{
}

Autofac现在可以解析正确的服务:

        var builder = new ContainerBuilder();
        builder.RegisterType<DateTimeProvider>().As<IDateTimeProvider>();
        builder.RegisterType<DateTimeUtcProvider>().As<IDateTimeUtcProvider>();
        builder.RegisterType<ServiceBoth>();
        builder.RegisterType<Service>();
        builder.RegisterType<UtcService>();
        var container = builder.Build();
        using (var scope = container.BeginLifetimeScope())
        {
            var sb = scope.Resolve<ServiceBoth>();
            var s = scope.Resolve<Service>();
            var su = scope.Resolve<UtcService>();

            Console.WriteLine($"Both: {sb.Dt}, {sb.UtcDt}; Norm: {s.Dt}; Utc: {su.Dt}");
            Console.ReadLine();
        }