【问题标题】:Verify any property changed from object with dozens of properties in C# from the client side从客户端验证从具有数十个 C# 属性的对象更改的任何属性
【发布时间】:2018-09-27 15:45:13
【问题描述】:

要确定来自 C# 对象的对象是否发生更改,我们必须单独测试每个属性,如下所示。有没有一种方法可以从 C# 对象中获取单个值,这很容易,无需进行所有这些比较并在客户端上使用它。该属性可能是某种散列,仅当该对象上的任何值发生更改时才会更改。 GetHashCode 本身似乎发生了变化,即使对象的属性相同。

以下属性来自此 C# 对象,我们测试它是否单独更改,但想知道是否有任何更改以在客户端上显示该项目的突出显示。

self.updated = ko.pureComputed(function () {
                return self.pts.isModified() || self.f.isModified() || self.ast.isModified() || self.reb.isModified() || self.ft.isModified() || self.fg3.isModified() || self.fg.isModified() || self.inGame.isModified();
        });

【问题讨论】:

  • 您可以实现 INotifyPropertyChange 并在其中一些更改时通知。是的,您必须编写大量的 setter 和 getter 并创建一个事件,但通过反思和想象力,您可能会做得更容易。

标签: javascript c# .net


【解决方案1】:

您可以覆盖 GetHashCode 并比较新对象和初始对象的哈希码:

public override int GetHashCode()
{
    int hash = 57;
    var props = GetType().GetProperties();

    foreach (var p in props)
    {
        if (p.GetValue(this, null) != null)
            hash = 27 ^ hash ^ p.GetValue(this, null).GetHashCode();

    }
    return hash;
}

还有更好的解决方案。您可以使用属性标记要跟踪的属性:

public override int GetHashCode()
        {
            int hash = 57;
            var props = GetType().GetProperties();

            UInt32 crc = 0;
            foreach (var p in props)
            {
                if (!p.GetCustomAttributes(typeof(YourAttribute), true).Any())
                {
                    if (p.GetValue(this, null) != null)
                        hash = 27 ^ hash ^ p.GetValue(this, null).GetHashCode();

                }
            }
            return hash;
        }

这样您就可以在跟踪中包含\排除某些属性。

【讨论】:

  • 但这又回到了我原来的问题。我不想为 100 个属性执行此操作。
  • 您可以循环遍历所有属性。我已经更新了示例
  • 如果您不想手动更新每个属性,最好的选择是编写一个脚本来为您完成。或者,如果您真的想让事情成为您未来的自己以及最终需要使用此代码的任何其他人的噩梦。您可以复制您的对象,然后使用反射来遍历原始对象的每个属性,以查看自上次复制后是否有任何值发生了变化。
【解决方案2】:

当您使用 SetProperty 方法时,这段代码应该通过 PropertyChanged 事件通知:

 class Class1 : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public int MyProp { get; protected set; }
        public string stringProp { get; protected set; }

        public void SetProperty(string propertyName, object value)
        {
            var properties = this.GetType().GetProperties();

            var property = properties.ToList().Where(x=> x.Name == propertyName ).FirstOrDefault() ;

            if (property != null)
            {
                property.SetValue(this, value);
                NotifyPropertyChanged(propertyName);
            }
        }

        // This method is called by the Set accessor of each property.  
        // The CallerMemberName attribute that is applied to the optional propertyName  
        // parameter causes the property name of the caller to be substituted as an argument.  
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }

使用示例:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var cl = new Class1();
            cl.PropertyChanged += propertyChanged;

            cl.SetProperty(nameof(cl.MyProp), 1);
            Console.ReadLine();
        }

        private static void propertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine (e.PropertyName);

        }
    }

参考:https://docs.microsoft.com/es-es/dotnet/api/system.componentmodel.inotifypropertychanged?redirectedfrom=MSDN&view=netframework-4.7.2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-13
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2014-06-15
    • 2015-03-26
    相关资源
    最近更新 更多