在 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 声明的名称,因此您可以只检查是否相等。)
我正在寻找一种方法来获取对象的两个实例之间的差异。 我编写的以下函数使用反射来满足手头的目的,但我想进一步增强它,以便它可以跳过具有特定数据注释的某些字段。例如在 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 声明的名称,因此您可以只检查是否相等。)