在 C# 中查找两个对象之间的差异

Find the variance between two Objects in C#

我正在寻找一种方法来获取对象的两个实例之间的差异。 我编写的以下函数使用反射来满足手头的目的,但我想进一步增强它,以便它可以跳过具有特定数据注释的某些字段。例如在 Entity Framework 模型

中使用的 '[NotMapped] & [JsonIgnore]' 注释
    public static List<ChangeSet> GetVariances<T>(this T previous, T updated)
    {
        List<ChangeSet> changeSet = new List<ChangeSet>();
        try
        {
            string[] excludedFields = { "Id", "DateCreated", "DateModified" };
            Type entityType = previous.GetType();
            FieldInfo[] fieldInfo = entityType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
            foreach (FieldInfo x in fieldInfo)
            {
                if (!excludedFields.Any(z => x.Name.Contains(z))){
                    ChangeSet change = new ChangeSet
                    {
                        Field = x.Name,
                        PreviousValue = x.GetValue(previous),
                        UpdatedValue = x.GetValue(updated)
                    };
                    if (!Equals(change.PreviousValue, change.UpdatedValue))
                        changeSet.Add(change);
                }
            }
        }
        catch (Exception ex)
        {
            var exception = ex.Message;
        }
        return changeSet;
    }

正在使用的模型示例:

[Table("ClientMaster")]
public partial class ClientMaster
{
    [Key]
    [JsonProperty(PropertyName = "id")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [JsonProperty(PropertyName = "clientId")]
    [Required, StringLength(250)]
    public string ClientId { get; set; }

    [JsonProperty(PropertyName = "approvalLevel")]
    [Required, StringLength(200)]
    public string ApprovalLevel { get; set; }

    [NotMapped]
    [JsonProperty(PropertyName = "attachments")]
    public List<ClientAttachmentModel> Attachments { get; set; }

    [JsonIgnore]
    public virtual UserInformation CreatedByUser { get; set; }

    [JsonIgnore]
    public virtual UserInformation ModifiedByUser { get; set; }

    [JsonIgnore]
    public virtual ICollection<TaskMaster> TaskMaster { get; set; }
}

谁能指导我使函数跳过某些数据注释。 任何帮助表示赞赏。

您可以使用 Attribute.IsDefined

检查字段或 属性 是否具有属性
var hasAttribute = Attribute.IsDefined(x, typeof(NotMappedAttribute));

如果您只是想找到装饰特定 属性 的属性,您需要在您的类型上调用 GetProperties,而不是像您那样调用 GetFields目前是。这是因为您的属性是装饰属性,而不是字段。 GetFields 将检索编译器生成的支持字段,这可能不是您想要的。您仍然可以用同样的方式进行价值比较。

现在,为了检查属性,由 GetProperties 编辑的数组 return 中的每个 PropertyInfo 对象将有一个数组 属性 CustomAttributes,它包含 属性 的装饰属性以及您为这些属性提供的任何参数的详细信息。如果您只想检查属性的存在而不关心参数,Magnus 的解决方案可以实现相同且更快。

(我还会提到,在您的代码示例中,使用 Name.Contains 意味着例如 ClientId 将被跳过,因为它的名称包含您列出的 Id作为排除字段。对于您声明的属性,Name 将只是 return 声明的名称,因此您可以只检查是否相等。)