0

我目前正在完成对象更改日志功能的工作,并想完善一些东西。由于我们有很多应该出现历史数据的 Web 表单/报告,我想知道是否有一种方法可以在不更改控件/报告的情况下实现它。目前,我有这种情况:

public class Foo {
    public string Property1 { get; set; }
    public DateTime CreatedDate { get; set;}

    public string GetHistoricalValue(string propertyName) 
    {
        HistoryHelper historyHelper = CreateHistoryHelper(this);
        return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
    }
...

public class HistoryHelper {
    public string GetHistoricalValue(string propertyName, DateTime date) {
    ...

因此,当有人想要获取 Property1 的历史数据时:

string historicalValue = fooInstance.GetHistoricalValue("Property1");

很明显,这种方法需要对当前应用程序进行大量更改。当我以常规方式访问 Property1 时,有没有办法让 Foo 类返回历史值:

string historicalValue = fooInstance.Property1;

诸如动​​态生成具有覆盖属性的子类或其他解决方案之类的东西?
这可能吗?

4

2 回答 2

1

初步答复

像这样的东西:

public class Foo {
    public bool HistoricalMode { get; set; }

    private string _property1;
    public string Property1 { 
        get { 
            if (HistoricalMode) {
                return GetHistoricalValue("Property1");
            } else {
                return _property1;
            }
        set {
            if (HistoricalMode){
                throw new NotSupportedException("Updates not possible in historical mode.");
            } else {
                _property1 = value;
            }
        }
    }
    public DateTime CreatedDate { 
        get {
            // Similar pattern as above
        }
        set {
            // Similar pattern as above
        }
    }

    public string GetHistoricalValue(string propertyName) {
        HistoryHelper historyHelper = CreateHistoryHelper(this);
        return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
    }
}

基本上,这个想法是在您的对象中保留一个布尔值,表明对象处于“历史模式”。如果是这样,请使用您的辅助方法。如果不是,则应用普通属性 getter/setter。

更新

我认为这个问题的解决方案需要改变你的框架(如果你的所有应用程序都有一个框架)。我会以您加载对象的方式寻求解决方案。希望您可以检测到何时需要在“历史模式”下以及何时在“正常模式”下需要对象。您现在从数据库中“读取”对象(记录),在历史模式下,您需要从更改日志功能中组合原始对象(从更改发生时开始)。这样,您当前的所有应用程序都可以(希望)保持原样。您需要做的“唯一”更改是在存储库类中。

顺便说一句,这一切都只是猜测。

于 2012-11-15T13:19:29.597 回答
0

您能否轻松影响Foo实例的创建方式?如果是这样,您可以例如创建 derived class HistoricalFoo : Foo、 make Property1virtual 并使用它的 getter 来改变它的行为。然后HistoricalFoo在需要历史数据时使用。它不是一个非常干净的对象模型,但可以完成工作。

public class Foo
{
    protected string _property1;
    public virtual string Property1
    {
        get { return _property1; }
        set { _property1 = value; }
    }

    public DateTime CreatedDate { get; set;}

    /* ... */
}

public class HistoricalFoo : Foo
{
    public override string Property1
    {
        get
        {
            return GetHistoricalValue("Property1");
        }
    }
}

如果这不适用,则可以将一些决策逻辑嵌入到Property1getter 中。在这种情况下,您必须更改Foo实例的内部状态 - 例如通过设置布尔标志IsInHistoryMode。但是,更改对象状态可能非常棘手,尤其是在多线程环境中。

public class Foo
{
    public bool IsInHistoryMode { get; set; }

    protected string _property1;
    public virtual string Property1
    {
        get
        {
            if(IsInHistoryMode)
            {
                return GetHistoricalValue("Property1");
            }

            return _property1;
        }
        set
        {
            _property1 = value;
        }
    }

    public DateTime CreatedDate { get; set;}

    /* ... */
}
于 2012-11-15T13:16:37.380 回答