【问题标题】:Late-binding collection to overloaded method后期绑定集合到重载方法
【发布时间】:2020-01-09 12:10:16
【问题描述】:

背景

我的代码接收一些 IProduct 类型的反序列化数据,但在运行时实现类是未知的。我应该将此数据传递给一个接受实现类实例的重载方法。

这可以通过使用 switch 语句来实现,但它看起来很笨重并且需要大量代码。我已经通过对单个实体使用后期绑定和运行时编译解决了这个问题,但我无法弄清楚如何为集合执行此操作。

解决单个实体的问题

如果我有一个 IProduct 类型的对象,并且想将它传递给正确的重载方法,该方法接受一个实现类,如玩具、食品、汽车或其他东西。如何在不创建大 switch 语句的情况下实现这一点?

给定以下方法和接口:

public interface IProduct
{
     string Name { get;}
     double Price { get;}
}

public void Store(Apple apple);
public void Store(Toy toy);
public void Store(Car car);

使用 switch 语句,它看起来像这样:

IProduct product = new Apple();

switch (product)
{
    case Apple apple:
        Store(apple);
        break;
    case Toy toy:
        Store(toy);
        break;
    case Car car:
        Store(car);
        break;
}

我已经设法使用后期绑定和运行时编译将其减少到以下。

IProduct product = new Apple();

Store((dynamic)product);

问题

但是,当涉及到集合时,我无法弄清楚如何以类似的方式进行后期绑定。

给定以下方法:

public static void Store(ICollection<Apple> apples);
public static void Store(ICollection<Toy> toys);
public static void Store(ICollection<Car> cars);

我如何通过这个:

ICollection<IProduct> products = new List<IProduct>() { new Apple()};

有没有办法在不使用大量神奇代码的情况下实现相同的目标?

【问题讨论】:

  • 你不会,好吧,不是没有一些黑客攻击。从根本上说,您违反了 SOLID 原则。如果你有一个苹果列表,那么使用一个苹果列表。如果您有一个产品列表,则将每个项目视为一个产品。
  • 这当然是一个简单的例子。我有兴趣解决这个问题或解释为什么不可能。只是出于兴趣,当我只提供 DTO 和一个接口时,您如何断定这违反了 SOLID,违反了哪些 SOLID 原则?

标签: c# dynamic polymorphism late-binding


【解决方案1】:

我不确定您的这些Store 方法位于何处。但在我看来,像这样的实现是正确的做事方式:

public interface IProduct
{
    string Name { get;}
    double Price { get;}

    void Store(IProduct product);
}

public class Apple : IProduct
{
    public Apple(string name, double price)
    {
        Name = name;
        Price = price;
    }

    public string Name { get; }
    public double Price { get; }

    public void Store(IProduct product)
    {
        throw new NotImplementedException();
    }
}

public class Toy : IProduct
{
    public Toy(string name, double price)
    {
        Name = name;
        Price = price;
    }

    public string Name { get; }
    public double Price { get; }

    public void Store(IProduct product)
    {
        throw new NotImplementedException();
    }
}

public class Playground
{
    void Test()
    {
        IProduct apple = new Apple("apple", 11);
        ICollection<IProduct> apples = new List<IProduct>() { new Apple("apple", 230)};
        apple.Store(apple);
        IProduct toy = new Toy("toy", 11);
        ICollection<IProduct> toys = new List<IProduct>() { new Toy("toy", 230)};
    }
}

【讨论】:

  • 您好@Siavash,感谢您尝试解决问题。在解决单个实体的问题时,此解决方案是否不需要像我上面展示的那样大的 switch 语句?
  • @Lillem4n 我认为不是,因为这里的想法是将实现移动到具体的类而不是其他任意位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 1970-01-01
相关资源
最近更新 更多