【问题标题】:Listen for object changes from the outside in C#在 C# 中从外部侦听对象更改
【发布时间】:2014-08-19 12:45:40
【问题描述】:

我有一个对象,我想监控它以防其数据发生变化。但是我不允许向对象添加额外的事件或接口,如 INotifyPropertyChanged,所以我需要纯粹从外部观察它,看看它是否在字符上发生了变化,并通过它的所有属性来识别发生了什么变化。

所以我基本上需要一个 FileSystemWatcher,但是对于一个对象。

C# 是否提供了我在这里寻找的任何功能?

【问题讨论】:

  • 好吧,如果您不能使用INotifyPropertyChanged,您将不得不缓存所有属性的值并定期检查当前值。
  • 对象是否可序列化?处理此问题的一种非常低效(但简单)的方法是定期将对象序列化到内存并将其与之前的序列化进行比较。但是,根据对象的大小以及需要轮询更改的频率,这可能对性能非常不利。
  • 该对象足够小,可以进行这种操作,并且它只是我公司私人测试软件上的代码,因此质量和性能不是重点。它只需要工作。看起来我必须自己定期轮询数据。

标签: c#


【解决方案1】:

您必须对其进行暴力破解并执行诸如捕获对象状态之类的操作,然后在需要检测更改时查找差异(通过定期轮询或在您需要了解差异的特定点) .

我相信,许多监控数据模型对象变化的系统(例如 RavenDB)就是这样做的。

我制作了一个快速而肮脏的控制台应用程序,大致可以满足您的需求。它应该足以给您一个想法,但如果您想在生产代码中使用它,则需要大量工作。 :)

class Program
{
    static void Main(string[] args)
    {
        DemoClass demo = new DemoClass { IntValue = 1, StringValue = "asdf" };

        var watcher = new DemoClassWatcher();
        watcher.Capture(demo);

        demo.StringValue = "1234";
        var results = watcher.Compare(demo); // results = "StringValue"
        demo.IntValue = 1234;
        results = watcher.Compare(demo); // results = "StringValue", "IntValue"
        watcher.Capture(demo);
        results = watcher.Compare(demo); // results = empty
    }
}

public class DemoClass
{
    public string StringValue { get; set; }
    public int IntValue { get; set; }
}

public class DemoClassWatcher
{
    private DemoClass lastRecorded = null;

    public void Capture(DemoClass objectToWatch)
    {
        lastRecorded = new DemoClass()
        {
            IntValue = objectToWatch.IntValue,
            StringValue = objectToWatch.StringValue
        };
    }

    public List<string> Compare(DemoClass currentObject)
    {
        var changes = new List<string>();
        var props = typeof(DemoClass).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var propertyInfo in props)
        {
            var currentVal = propertyInfo.GetValue(currentObject);
            var prevVal = propertyInfo.GetValue(lastRecorded);
            if (currentVal is IComparable)
            {
                if ((currentVal as IComparable).CompareTo(prevVal) != 0)
                    changes.Add(propertyInfo.Name);
                continue;
            }

            throw new NotSupportedException("Properties must support IComparable until someone fixes me up");
        }
        return changes;
    } 
}

【讨论】:

  • 有趣的想法 Rob。我会调查一下,看看这可以很好地解决我手头的问题。
  • 我将此标记为答案,因为它与 Type 和 GetProperties 方法一起使用的方式。很容易实现。
【解决方案2】:

您无法侦听不存在的事件,但您可以轮询状态并将它们与之前的状态进行比较。

伪代码:

///initial config: 
yourObject = getAReferenceToTheObject();
previousState = new ObjectClass(yourObject);

///somewhere in a thread/loop
if (previousState.SomeProperty!= yourObject.SomeProperty){
    //state changed for SomeProperty on yourObject
}
//TODO: check other properties
previousState = new ObjectClass(yourObject); //implement copy constructor

【讨论】:

    猜你喜欢
    • 2021-10-06
    • 2010-11-07
    • 2012-04-23
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 2022-01-16
    相关资源
    最近更新 更多