c# - 给定泛型类型参数的类型,动态选择组件的类型

标签 c# design-patterns generics

我似乎经常遇到这样的情况:我有一个抽象类型,需要根据它具有的具体实现进行不同的处理。

举个例子,抽象类 Payment 可以被子类化为 class CreditCardclass StoredCredit。为了实际处理付款,我们希望使用

的实现
interface IPaymentTaker {
  PaymentProcessingResult Process(Payment payment); }

即要么

class CreditCardPaymentTaker : IPaymentTaker { ... }

class StoredCreditPaymentTaker : IPaymentTaker { ... }

过去我已经将 IDictionary 注入(inject)到父组件中然后完成

_paymentTakers[payment.GetType()].Process(payment);

这样做的缺点是 IPaymentTaker 实现的类型不够强,因此 Process 方法的第一位必须是:

Process(Payment payment)
{
  var creditCardPayment = payment as CreditCardPayment;
  if (creditCardPayment == null)
    throw new Exception("Payment must be of type CreditCard");
}

我确信我正在尝试实现的模式必须有一个名称,但我不知道它是什么!

理想情况下我会

(a) 能够仅根据付款类型实例化 PaymentProcessor,而无需创建字典;

(b) 能够拥有只接受它们可以使用的子类的强类型 PaymentProcessors。

有人有解决这个问题的好方法吗?

最佳答案

您可以使用visitor来解决这个问题:

interface IPaymentVisitor {
  void Visit(CreditCard payment);
  void Visit(StoredCredit payment);
}

abstract class Payment {
  public abstract void Accept(IPaymentVisitor visitor);
}
class CreditCard : Payment {
  public override void Accept(IPaymentVisitor visitor) {
    visitor.Visit(this);
  }
}
class StoredCredit : Payment {
  public override void Accept(IPaymentVisitor visitor) {
    visitor.Visit(this);
  }
}

class PaymentTaker : IPaymentVisitor, IPaymentTaker {
  public void Visit(CreditCard payment) {
    // ... 
  }

  public void Visit(StoredCredit payment) {
    // ... 
  }

  public PaymentProcessingResult Process(Payment payment) {
    payment.Accept(this);
    // ...
  }
}

如果您仍想将不同的付款接受者分开,或者您的层次结构不稳定,则可以使用 acyclic visitor (pdf) :

interface IPaymentVisitor {
}

interface IPaymentVisitor<TPayment> : IPaymentVisitor where TPayment : Payment {
  void Visit(TPayment payment);
}

abstract class Payment {
  public abstract void Accept(IPaymentVisitor visitor);
}
class CreditCard : Payment {
  public override void Accept(IPaymentVisitor visitor) {
    if (visitor is IPaymentVisitor<CreditCard>) {
      ((IPaymentVisitor<CreditCard>)visitor).Visit(this);
    }
  }
}
class StoredCredit : Payment {
  public override void Accept(IPaymentVisitor visitor) {
    if (visitor is IPaymentVisitor<StoredCredit>) {
      ((IPaymentVisitor<StoredCredit>)visitor).Visit(this);
    }
  }
}

class CreditCardPaymentTaker : IPaymentVisitor<CreditCard>, IPaymentTaker {
  public void Visit(CreditCard payment) {
    // ...
  }
  public PaymentProcessingResult Process(Payment payment) {
    payment.Accept(this);
    // ...
  }
}
class StoredCreditPaymentTaker : IPaymentVisitor<StoredCredit>, IPaymentTaker {
  public void Visit(StoredCredit payment) {
    // ...
  }
  public PaymentProcessingResult Process(Payment payment) {
    payment.Accept(this);
    // ...
  }
}

关于c# - 给定泛型类型参数的类型,动态选择组件的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3424154/

相关文章:

c# - 在生成的 Word 文档中格式化单元格

c# - 如何根据模型中是否有这样的值来显示一个元素?

c++ - 特定子类的装饰器

wpf - MVVM View 模型与 View 之间的关系

Java 泛型和 Hadoop : how to get a class variable

c# - 如何获得复杂的枚举值字符串表示

c# - 了解 LINQ to SQL 中的 .AsEnumerable()

c++ - 用于分组和管理许多不同的内存中索引的解决方案

generics - Kotlin 泛型类属性

swift - 如何比较 Swift 中的泛型对象?