如何使用定制实现重写超类属性值

本文关键字:超类 属性 重写 实现 何使用 | 更新日期: 2023-09-27 18:14:07

我在现有的3层"核心"应用程序代码中的逻辑层项目中有一个超类"Entity",从其中继承了两个具体类"RiskEntity"answers"PolicyEntity"(在同一个核心项目中)。超类拥有一个公共属性"Loss",它不会被两个子类覆盖。此属性由此核心项目中的其他代码使用。该属性的实现引用了该核心项目中的其他类/属性。

对于一个特殊的用例,我要求以不同的方式实现属性的getter。如果可能的话,我希望定制实现存在于上面提到的"核心"c#项目之外,并且我希望应用程序是可配置的,以便指示它在该属性从我的核心项目中引用时使用定制实现。

谁能指出一个优雅的模式/技术来实现这一点?我想知道如何在getter中使用helper接口,并根据(例如)项目设置使用反射来实例化该接口的正确实现。但是,即使这是沿着正确的路线,我不确定定制的实现如何能够在核心项目代码之外生存。

也欢迎其他建议。谢谢。

如何使用定制实现重写超类属性值

既然你描述了Loss属性如何计算的不同实现,这向我建议了策略模式。您可以确保基本Entity类使用默认实现,但Entity子类可以使用替代实现来构造。因此,我将首先在您的核心项目中定义一个接口,该接口可以在核心程序集之外的程序集中实现,只要它们有对它的引用。这个主题有很多变体,如果没有看到更多的代码,很难准确地知道哪个适合您的情况,但下面给出了一个大致的轮廓。

首先,核心项目中的Strategy接口和默认实现:
public interface ILossCalculator
{
   decimal CalculateLoss(); //maybe needs parameters, perhaps even the Entity itself?
}
public class DefaultLossCalculator : ILossCalculator
{
   public DefaultLossCalculator(Dependency a, OtherDependency b)
   {
       //just an example, but here we inject the other classes that the 
       //default implementation requires to do the calculation.
   }
   public decimal CalculateLoss()
   {
       //default implementation ...
       return totalLoss;
   }
}

接下来,Entity类和派生类,再次在核心项目中。

public abstract class Entity
{
   private ILossCalculator _lossCalculator;
   protected Entity(Dependency a, OtherDependency b)
   {
       _lossCalculator = new DefaultLossCalculator(a, b);
   }
   protected Entity(ILossCalculator lossCalculator)
   {
       _lossCalculator = lossCalculator;
   }
   public decimal Loss
   {
      get
      {
         return _lossCalculator.CalculateLoss();
      }
   }
}
public class RiskEntity : Entity
{
    public RiskEntity(Dependency a, Dependency b) : base(a, b)
    {
    }
    public RiskEntity(ILossCalculator lossCalculator) : base(lossCalculator)
    {
    }
    //rest of implementation
}
//Other derived class(es) omitted - you get the idea, though...

构建Entity派生对象的客户端代码现在可以推送ILossCalculator接口的不同实现,即使实现是在核心项目之外定义的。为了从配置中选择要使用的ILossCalculator实现,我可能会创建一个Factory,您将使用它来构建Entity子类,这些子类可以配置为当创建Entity时,它将使用ILossCalculator的自定义实现。客户端的视图类似于:

var factory = new EntityFactory();
factory.LossCalculationStrategy(() => new MyCustomLossCalculator());
var entity = factory.CreateRiskEntity(); //returns a RiskEntity constructed with the custom loss calculator

我不确定我是否很了解您的需求,但这听起来非常像控制反转(IOC)框架的一个很好的任务。我的团队使用温莎城堡作为IOC。

简而言之,框架允许您配置存储库以返回类型为X的对象来满足对类型为Y的对象的请求(其中X实现或继承自Y)。您可以在代码或.config文件中定义这种关联,它应该满足您的"我希望应用程序是可配置的"要求。

根据你在属性的getter中需要的不同,你可以使用一个装饰器(参见http://en.wikipedia.org/wiki/Decorator_pattern)来包装对象,或者用一个复制构造函数包装一个子类。"prefer composition"指导原则更倾向于装饰器。如果您需要访问定制实现中的受保护成员,我只会查看子类选项。