如何使用bespoke实现覆盖超类属性值?

时间:2011-11-11 17:12:07

标签: c#

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

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

有人能指出一种优雅的模式/技术来实现这一目标吗?我想知道在getter中使用helper接口,并使用反射来实例化该接口的正确实现,基于(例如)项目设置。但即使这是正确的,我也不确定定制实现如何能够存在于核心项目代码之外。

也欢迎其他建议。感谢。

2 个答案:

答案 0 :(得分:0)

我不确定我是否理解你的要求,但这听起来非常像是一个控制反转(IOC)框架的好任务。我的团队使用Castle Windsor作为IOC。

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

根据属性getter中所需的差异,您可以使用装饰器(请参阅http://en.wikipedia.org/wiki/Decorator_pattern)来包装对象,也可以使用复制构造函数包装子类。 “首选组合”指南有利于装饰者。如果您需要在定制实现中访问受保护的成员,我只会查看子类选项。

答案 1 :(得分:0)

由于您描述了如何计算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