这是组合而非继承的恰当用法吗

本文关键字:用法 继承 组合 | 更新日期: 2023-09-27 18:20:23

背景

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

[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
    }
}

有人能提供一些反馈吗?我是否正在沿着关于可组合性/继承的正确道路前进

这是组合而非继承的恰当用法吗

ChangeProperty是虚拟的,所以如果你只想修改继承的("子")类之一的行为,你可以这样做:

[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);
    }
}

另一方面,如果你想"修改"(或者更好,我会说增强)每个BaseObject的ChangeProperty方法,我会按照你的方式。

我可能会使用更"通用"的方法,比如:

[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框架!

您面临的问题很常见:具有交叉概念("方面")的预兆方法,如日志记录、安全性、ecc。。。

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