Найти дисперсию между двумя объектами в C # - PullRequest
0 голосов
/ 08 ноября 2018

Я ищу способ получить дисперсию между двумя экземплярами объекта. Следующая функция, которую я написал, использует отражение для достижения поставленной цели, но я хочу немного улучшить ее, чтобы она могла пропускать определенные поля с конкретными аннотациями данных. Например, аннотация «[NotMapped] & [JsonIgnore]», используемая в моделях Entity Framework

    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 голосов
/ 08 ноября 2018

Если вы ищете только то, какие атрибуты украшают определенное свойство, вам нужно будет вызвать GetProperties для вашего типа вместо GetFields, как вы в настоящее время.Это потому, что ваши атрибуты украшают свойства, а не поля.GetFields вернет сгенерированные компилятором поля поддержки, что, вероятно, не то, что вам нужно.Вы все еще можете выполнить сравнение значений таким же образом.

Теперь, чтобы проверить атрибуты, каждый объект PropertyInfo в массиве, возвращаемый GetProperties, будет иметь свойство массива CustomAttributes, которое содержит деталииз атрибутов украшения этого свойства и любых аргументов, которые вы предоставили этим атрибутам.Если вы просто хотите проверить наличие атрибута и не заботитесь об аргументах, решение Magnus достигает того же и быстрее.

(я также упомяну это в вашем примере кода, используя Name.Containsбудет означать, что, например, ClientId будет пропущено, поскольку его имя содержит Id, которое вы указываете как исключенное поле. Name для объявленных вами свойств просто вернет имя как объявленное, чтобы вы моглипросто проверьте на равенство.)

0 голосов
/ 08 ноября 2018

Вы можете просто проверить, имеет ли поле или свойство атрибут, используя Attribute.IsDefined

var hasAttribute = Attribute.IsDefined(x, typeof(NotMappedAttribute));
...