2012-01-18 51 views
0

更新设计与接口的类

什么是设置这个类的最佳方式?即致电SetupInstruction()方法?我想让这个方法是虚拟的,所以覆盖的类可以有自己的实现。在重写的类中,我将设置其他对象/属性。

public abstract class InstructionInfo : IInstruction 
{ 
    protected readonly IUserSession UserSession; 
    protected readonly IReadOnlySession ReadOnlySession; 

    protected InstructionInfo(int instructionID) 
    { 
     InstructionID = instructionID; 
    } 

    protected virtual void SetupInstruction() 
    { 
     _myInstruction = null; //call db and set up... 
    } 

    #region interface members 

    private Instruction _myInstruction; 
    public Instruction MyInstruction 
    { 
     get 
     { 
      **SetupInstruction();** 
      return _myInstruction; 
     } 
     private set { _myInstruction = value; } 
    } 

    #endregion 
} 
+4

我想你可能会更好地服务于http:// codereview。stackexchange.com – 2012-01-18 20:34:09

+0

你没有在构造函数中设置它的原因是什么? – 2012-01-18 20:43:00

+0

@JonHanna Resharper抱怨在构造函数中设置虚拟成员调用......我对于副作用可能会产生什么影响...... – Haroon 2012-01-18 20:44:42

回答

0

我认为我不完全理解你的问题,但你应该做的MyInstructionprotected二传手,所以覆盖类可以将其设置在SetupInstruction()

你也应该给财产一个更好的名字,例如Instruction而不是MyInstruction

+0

我会,但指令已经是一个实体对象的名称,我打开其他名称:) – Haroon 2012-01-18 20:50:27

1

这一切都取决于你打算如何使用代码。如果您希望安装过程是内部的,那么您可能需要从基本类型的构造函数中调用该方法。然后可以通过重写该方法,通过派生类型对安装程序进行自定义。同样,如果你想运行一个步一些常见设置任务可能发生的自定义设置,您可以创建一个类似的设置:

protected InstructionInfo(...) 
{ 
    // ... 

    SetupInstruction(); 
} 

private void SetupInstruction() 
{ 
    // Common setup 
    // ... 

    // Custom setup 
    SetupInstructionCore(); 
} 

// Either an optionally overriddable method 
protected virtual void SetupInstructionCore() 
{ 
} 

// Or a required override 
protected abstract void SetupInstructionCore(); 
+0

我想这个类的设置要么设置在这个非常类,要么允许类从这个类继承并设置这个类,看起来好像你提供的可选重写方法可能是我需要的。我只是想弄清楚我会在什么地方建立这个类,看起来好像你在暗示构造函数...... – Haroon 2012-01-18 20:43:31

+0

@Haroon如果创建对象时需要设置,那么是的。它还允许基类在发生安装时进行控制,而不是等待某个外部调用者。 – 2012-01-18 20:51:14

+0

这正是我想要的,我希望类设置为asap,同样的规则适用于继承的类,它必须设置,然后在其他地方使用它很好,我可以添加另一个方法到我的接口调用设置()并执行里面的所有操作?这会更有意义吗?更合乎逻辑?将其视为抽象并强制执行? – Haroon 2012-01-18 20:56:32

0

可能是我错过了什么,而只是一个样本:

// a Base abstract class 
public abstract class MyAbs 
{ 
    public MyAbs() {   
     Init(); 
    } 

    public virtual void Init(){ 
     "Do base".Dump(); 
    } 
} 

//derived 
public class Derived : MyAbs 
{ 
    public override void Init(){ 
     "Do child".Dump(); 
    } 
} 

代码运行,样品

Derived ab = new Derived(); 

输出?基于OO的原则是:

"Do child" 

希望这是你想要的。

+0

不知道为什么resharper在构造函数中抱怨虚拟成员调用......有什么影响? – Haroon 2012-01-18 20:48:04

+0

@Haroon:考虑到'ctor'即将构造调用虚拟方法的对象,让我们来派生类,用它自己的实现来干扰基类的初始化。因为孩子的ovveride将被称为第一,而不是基类。您可以提供一个'Factory'类,它用'Init()'调用构造基类型的对象,避免以这种方式在构造函数中使用它。 – Tigran 2012-01-18 20:51:02

+0

@哈龙:一个很好的解释,为什么是很好,以避免调用'ctor'内的虚拟方法可以在这里找到http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor – Tigran 2012-01-18 20:53:28

0

Your InstructionInfo是一个实体。设置方法应该被移动到一个存储库类,例如。例如,InstructionInfoRepository.GetInstructionInfoByID()。

您可以稍后将已上传的InstructionInfoRepository(例如IInstructionInfoRepository)注入其他组件以解耦数据库访问指令实例化逻辑。您还可以在单​​元测试期间将一个模拟的IInstructionInfoRepository注入这些相同的组件,以避免单元测试期间的外部资源依赖。在集成测试期间,您可以测试IInstructionInfoRepository的具体实现。

+0

可以做到这一点,事实上,这正是我所做的大声笑,然后我意识到我是多么的错,所以我朝另一个方向移动,我的类实现了一个在各个地方使用的接口,我的继承类实现了一个略有不同的接口这一个,很多功能都不是那么容易得到使用存储库... – Haroon 2012-01-18 20:52:57

+0

你可以不考虑你的存储库中的各种接口实现。您可以将界面特定的细节委托给各种策略。我并不熟悉具体的细节,但我通常倾向于将数据访问和实例责任分离到存储库和/或工厂。如果接口实现仅因操作/方法实现而异,则将数据访问视为单独的问题。 – 2012-01-18 21:00:19

0

大多数情况下,我只是设计一个类来在自己的构造函数中设置它自己需要的那些字段,并让派生类设置它们的属性。

如果我想要一个特定的字段被设置为被覆盖的方式,那么我会通过一个延迟加载的属性来使用它。

public abstract class MyClass 
{ 
    private SomeType _someField = null; // Never touch this field in any member but 
             // the SomeProp property 
             // Maybe use Lazy<SomeType> to make this more obvious. 
    protected SomeType CreateSomeType(); 
    public SomeType SomeProp 
    { 
    get 
    { 
     return _someField = _someField ?? CreateSomeType(); 
    } 
    } 
} 

现在我不会去想“设置”的对象,我只是充当如果它总是有SomeProp蓄势待发,只要我不要在构造函数中使用它,它”我会工作。

如果这在特定情况下不起作用,我会考虑工厂模式或存储库模式。