在C#中使用Lambda确定非等于的属性值

时间:2014-01-21 16:15:29

标签: c# generics properties lambda propertyinfo

在我的应用程序中的某个时刻,我收到了来自数据库查询的数据字典。我将该数据和实例作为对象并调用RestoreState()方法,该方法获取数据字典并将值应用于新实例中的相应属性。

RestoreState()方法完成后,我会将值字典传递给对象,并将其传递给名为OriginalValues的属性,如下所示:

myObject.EnableChangeTracking = true;
myObject.OrginalValues = dictionaryData;

稍后,用户通过UI对对象进行一些更改并按下save。然后我想比较对象属性的现有状态和原始状态,因此我可以构造一个更新语句来发送给SQL。

问题(和问题)是我的lambda表达式将我当前的属性值与字典中的值进行比较不起作用。 OriginalValues字典有23个项目,我的Lambda返回的字典包含14.在我的单元测试中,我只更改2.为什么我还找回了12个未更改的其他值?

我的GetChanges方法:

    public Dictionary<string, object> GetChanges()
    {
        if(!EnableChangeTracking || OrginalValues==null || !OrginalValues.Any())
            return new Dictionary<string, object>();

        // Only get properties that have changed.
        var changedProperties = 
            this
            .GetType()
            .GetProperties()
            .Where(p => p.GetValue(this, null) != OrginalValues[p.Name])
            .ToDictionary(p => p.Name, p => p.GetValue(this));

        return changedProperties;
    } 

我的OriginalValues字典包含:

  • [0] {[AssetId,1]} System.Collections.Generic.KeyValuePair
  • [1] {[SubFeatureId,0]} System.Collections.Generic.KeyValuePair
  • [2] {[OrgNumber,8555]} System.Collections.Generic.KeyValuePair
  • [3] {[LaneLocationId,]} System.Collections.Generic.KeyValuePair
  • [4] {[StatusId,1]} System.Collections.Generic.KeyValuePair
  • [5] {[AssetCode,1]} System.Collections.Generic.KeyValuePair
  • [6] {[注意,这里没什么可看的。]} System.Collections.Generic.KeyValuePair
  • [7] {[DateActivated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [8] {[DateInactivated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [9] {[EnteredBy,JS]} System.Collections.Generic.KeyValuePair
  • [10] {[DateEntered,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [11] {[CreatedBy,JS]} System.Collections.Generic.KeyValuePair
  • [12] {[UpdatedBy,JS]} System.Collections.Generic.KeyValuePair
  • [13] {[DateCreated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [14] {[DateUpdated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [15] {[IsActive,True]} System.Collections.Generic.KeyValuePair
  • [16] {[AssetAttributes,System.Collections.Generic.List`1 [FISDC.Models.AssetAttribute]]} System.Collections.Generic.KeyValuePair
  • [17] {[AssetReasons,System.Collections.Generic.List`1 [FISDC.Models.AssetReason]]} System.Collections.Generic.KeyValuePair
  • [18] {[AssetObjects,System.Collections.Generic.List`1 [FISDC.Models.AssetObject]]} System.Collections.Generic.KeyValuePair
  • [19] {[SubFeature,]} System.Collections.Generic.KeyValuePair
  • [20] {[EnableChangeTracking,False]} System.Collections.Generic.KeyValuePair
  • [21] {[IsValid,False]} System.Collections.Generic.KeyValuePair
  • [22] {[OrginalValues,]} System.Collections.Generic.KeyValuePair

我的Lambda表达式返回:

  • [0] {[AssetId,1]} System.Collections.Generic.KeyValuePair
  • [1] {[SubFeatureId,0]} System.Collections.Generic.KeyValuePair
  • [2] {[OrgNumber,2222]} System.Collections.Generic.KeyValuePair
  • [3] {[StatusId,1]} System.Collections.Generic.KeyValuePair
  • [4] {[DateActivated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [5] {[DateInactivated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [6] {[DateEntered,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [7] {[CreatedBy,SomeoneElse]} System.Collections.Generic.KeyValuePair
  • [8] {[DateCreated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [9] {[DateUpdated,1/21/2014 9:12:08 AM]} System.Collections.Generic.KeyValuePair
  • [10] {[IsActive,True]} System.Collections.Generic.KeyValuePair
  • [11] {[EnableChangeTracking,True]} System.Collections.Generic.KeyValuePair
  • [12] {[IsValid,False]} System.Collections.Generic.KeyValuePair
  • [13] {[OrginalValues,System.Collections.Generic.Dictionary`2 [System.String,System.Object]]} System.Collections.Generic.KeyValuePair

我在单元测试中更改的唯一属性是OrgNumber和CreatedBy。有人有什么想法吗?

更新

以下是我用来更新属性的代码,然后调用GetChanges()方法。

        myObject.OrgNumber = "2222";
        myObject.CreatedBy = "SomeoneElse";

        myDictionary = myObject.GetChanges();

更新2

我很好奇,如果问题是我的词典是<string, object>而且我正在比较参考和非参考类型?那么int值是否与对象进行比较并返回?我不知道。

更新3

感谢@TTat的工作方法

    public Dictionary<string,object> OrginalValues { get; set; }

    public Dictionary<string, object> GetChanges()
    {
        if(!EnableChangeTracking || OrginalValues==null || !OrginalValues.Any())
            return new Dictionary<string, object>();

        // Only get properties that have changed.
        var changedProperties = 
            this
            .GetType()
            .GetProperties()
            .Where(p => !System.Attribute.IsDefined(p, typeof(IgnoreAttribute))
                         && !Equals(p.GetValue(this, null), OrginalValues[p.Name]))
            .ToDictionary(p => p.Name, p => p.GetValue(this));

        return changedProperties;
    } 

1 个答案:

答案 0 :(得分:3)

由于您的字典为<string, object>!=将使用参考比较。使用Equals方法检查值。这使用了基本的Equals,它将为你处理null结果。

Where(p => !Equals(p.GetValue(this, null), OrginalValues[p.Name]))