【问题标题】:Why is my implementation always calling the same derived class?为什么我的实现总是调用同一个派生类?
【发布时间】:2019-10-22 00:38:37
【问题描述】:

我有一个接受 Type 作为构造函数参数的基类,以及从该基类继承的两个派生类。我也有那个基类的接口,我注入它以在其他地方使用。

当我调用基方法“FormatValue”,将不同类型作为参数传递时,我总是得到相同的结果(它调用其中一个类中的方法,忽略我的类型参数)。

我做错了什么?

public interface IFormatService
{
    string FormatValue(object value);
}
public abstract class FormatService : IFormatService
{
    protected FormatService(Type type)
    { }

    public abstract string FormatValue(object value);
}

public static class Program
{
    private static void Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
            .AddSingleton<IFormatService, CurrencyFormat>()
            .AddSingleton<IFormatService, DateTimeFormat>()
            .BuildServiceProvider();

        var formatService = serviceProvider.GetService<IFormatService>();

        Console.WriteLine(formatService.FormatValue(DateTime.Now));
        Console.WriteLine(formatService.FormatValue(200));

        Console.ReadLine();
    }
}

public class CurrencyFormat : FormatService
{
    public CurrencyFormat() : base(typeof(decimal))
    {
    }

    public override string FormatValue(object value) => "CurrencyFormatter";
}

public class DateTimeFormat : FormatService
{
    public DateTimeFormat() : base(typeof(DateTime))
    {
    }

    public override string FormatValue(object value) => "DateTimeFormatter";
}

当前结果:

DateTimeFormatter
DateTimeFormatter

预期结果:

DateTimeFormatter
CurrencyFormatter

【问题讨论】:

  • 您的第二次注册.AddSingleton&lt;IFormatService, DateTimeFormat&gt;() 覆盖了前一次,您应该使IFormatService 通用IFormatService&lt;T&gt; 正常工作。
  • 谢谢!但是如何注册一个通用接口呢?作为瞬态?以及如何获得服务,因为我为我拥有的每种类型声明了每一种服务?
  • 你可以像这样.AddSingleton&lt;IFormatService&lt;DateTime&gt;, DateTimeFormat&gt;()注册单身。
  • 但是我必须为我拥有的每种类型声明一个服务?喜欢var datetimeFormatService = serviceProvider.GetService&lt;IFormatService&lt;DateTime&gt;&gt;(); var currencyFormatService = serviceProvider.GetService&lt;IFormatService&lt;decimal&gt;&gt;();

标签: c# oop dependency-injection abstract-class derived-class


【解决方案1】:

下面指出的代码会覆盖您之前的 CurrencyFormat 注册,因此它始终解析为 DateTimeFormat。

var serviceProvider = new ServiceCollection()
    .AddSingleton<IFormatService, CurrencyFormat>()
    .AddSingleton<IFormatService, DateTimeFormat>() <---------
    .BuildServiceProvider();

【讨论】:

  • 考虑在问题中添加 Alessandro 评论中的信息,它说明了如何解决它
  • @bradbury9 虽然这是真的,但我认为“解决方案”不会在任何地方引领 OP。您将必须为应格式化的每种类型解析。不是我所说的方便。
【解决方案2】:

如果你想根据参数的类型调用不同的方法,有很多方法可以做到。

一种方法是使用dynamic 在运行时选择最佳重载:

public interface IFormatService
{
    string FormatValue(object value);
}

public class FormatService : IFormatService
{
    public string FormatValue(object value)
    {
        dynamic valueAsDynamic = value;

        return FormatValueDynamic(valueAsDynamic);
    }

    string FormatValueDynamic(dynamic value) => FormatValuePrivate(value);

    string FormatValuePrivate(DateTime value) => "DateTimeFormatter";

    string FormatValuePrivate(decimal value) => "CurrencyFormatter";

    string FormatValuePrivate(object value) => throw new NotSupportedException();
}

这样你可以添加你需要的所有方法。

【讨论】:

    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2019-09-02
    • 2013-07-17
    • 2019-07-16
    相关资源
    最近更新 更多