在C#中找到两个对象之间的方差

时间:2018-11-08 12:54:04

标签: c# .net system.reflection variance

我正在寻找一种获取对象的两个实例之间的差异的方法。 我编写的以下函数使用反射实现手头的目的,但是我想进一步增强它,以便可以跳过带有特定数据注释的某些字段。例如,在实体框架模型中使用的“ [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; }
}

任何人都可以指导我使该功能跳过某些数据注释。 任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:5)

您可以使用Attribute.IsDefined

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

答案 1 :(得分:3)

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

现在,要检查属性,由PropertyInfo返回的数组中的每个GetProperties对象将具有一个数组属性CustomAttributes,其中包含该属性的修饰属性的详细信息以及您所用的任何参数提供了那些属性。如果您只想检查属性的存在而不必关心参数,那么Magnus的解决方案可以实现相同且更快的结果。

(我还要提到,在您的代码示例中,使用Name.Contains意味着例如,ClientId将被跳过,因为其名称包含Id,您将其列为对于已声明的属性,Name将仅返回声明的名称,以便您可以检查是否相等。)