这是否适合使用Composition over Inheritance?

时间:2014-09-03 06:51:34

标签: c# inheritance composition

背景

我有一个基类BaseObject,我想在整个应用程序中使用它。 BaseObject实际上只定义了应用程序中所有对象必须具有的公共Guid;此外,BaseObject定义了许多方法来帮助生成属性更改事件。这导致了以下代码:

[DataContract]
public abstract class BaseObject
{
    private Guid id;
    [DataMember]
    public Guid Id
    {
        get { return id; }
        set { ChangeProperty(ref id, value, "Id"); }
    }

    protected virtual void ChangeProperty<T>(
        ref T property,
        T value,
        string propertyName)
    {
        // Change the property and generate events
    }
}

问题

由于所有对象都必须从BaseObject继承,这意味着派生类会有一个“固定”的对象。 ChangeProperty。我想修改ChangeProperty,以便输出到控制台,我将不得不修改基类。

潜在解决方案

我现在重写的代码如下所示;我有一个单独的类来处理属性更改:

public interface IPropertyChangeHelper
{
    void ChangeProperty<T>(
        ref T property,
        T value,
        string propertyName,
        PropertyChangingEventHandler changingHandler,
        PropertyChangedEventHandler changedHandler);
}

[DataContract]
public abstract class BaseObject
{
    // passed in during construction
    private readonly IPropertyChangeHelper propertyChangeHelper; 

    private Guid id;
    [DataMember]
    public Guid Id
    {
        get { return id; }
        set { ChangeProperty(ref id, value, "Id"); }
    }

    // Forwarding method
    protected virtual void ChangeProperty<T>(
        ref T property,
        T value,
        string propertyName)
    {
        // Forward to helper
    }
}

有人可以提供一些反馈意见,说明我是否继续沿着正确的路线进行可组合性/继承?

1 个答案:

答案 0 :(得分:0)

ChangeProperty是虚拟的,所以如果你只是想修改一个继承的(&#34; child&#34;)类的行为,你可以这样做:

[DataContract]
public class MyObject: BaseObject
{    
    protected virtual void ChangeProperty<T>(
        ref T property,
        T value,
        string propertyName)
    {
        // Do my own stuff
        base.ChangeProperty(property, value, propertyName);
    }
}

另一方面,如果你想&#34;修改&#34; (或者更好,我会说 augment )每个BaseObject的ChangeProperty方法,我会按你的方式进行。

我可能会使用更多&#34; general&#34;方法,如:

[DataContract]
public abstract class BaseObject
{
    public IPropertyChangeHelper propertyChangeHelper { get; set; }

    ...

    public void ChangeProperty<T>(
        ref T property,
        T value,
        string propertyName)
    {
        if (propertyChangeHelper != null)
           propertyChangeHelper.beforeChange(value, propetyName)
        ...

        if (propertyChangeHelper != null)
           propertyChangeHelper.afterChange(value, propetyName)
    }
}

相应地修改界面。但取决于个人喜好/交易安全(谁会使用你的课程?)的灵活性。

也就是说,如果您不想使用AOP框架!

您面临的问题非常普遍:具有交叉概念(&#34;方面&#34;)的扩展方法,如日志记录,安全性,ecc ......

C#本身没有AOP功能,但有一些.NET库可以帮助您。 举个例子,请看一下PostSharp,或者访问Castle DynamicProxy,或者再次阅读MSDN上的这篇文章。