首页 > 解决方案 > EF Core 自定义属性不适用于 modeBuilder.Model.GetEntityTypes() 上的对象类型

问题描述

我有一个自定义属性类定义如下:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class JsonFieldAttribute : Attribute
{
    public JsonFieldAttribute()
    {
    }
}

通过使用反射在任何类上获取此属性用法都非常完美。没有什么花哨。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    [JsonField]
    public string Primitive { get; set; }

    [JsonField]
    public Address NonPrimitive { get; set; }
}

但是通过在 DbContexts 的 OnModelCreating 上使用 modeBuilder.Model.GetEntityTypes() 仅适用于原始类型。似乎任何类类型都被忽略了。

  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
        base.OnModelCreating(modelBuilder);

        foreach (var entityTypes in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityTypes.GetProperties())
            {
                var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
                if (memberInfo == null)
                {
                    continue;
                }
                var attr = Attribute.GetCustomAttribute(memberInfo, typeof(JsonFieldAttribute));
                // I've tried various combinations here, but all of them failed
                // var attr = memberInfo?.GetCustomAttribute<JsonFieldAttribute>();
                if (attr == null)
                {
                    continue;
                }
                Console.WriteLine($"Custom attribute {property.Name} {attr.GetType().Name}");
            }
        }
  }

输出包含以下内容:

自定义属性 Primitive JsonFieldAttribute

我正在使用 .NET Core 2.1.403 并打包 Microsoft.AspNetCore.All v 2.1.5。知道为什么 NonPrimitive 不起作用吗?

标签: c#ef-core-2.1

解决方案


这是因为 EF Core 术语的集合和实体(拥有或常规)类型(换句话说,导航属性)不是属性,而是导航,并且不包含在GetProperties方法结果中,而是可以使用GetNavigations方法检索。

由于IPropertyINavigation共享一个共同的基础IPropertyBase,您可以将它们与Concat方法结合起来并像这样更改您的循环:

foreach (var property in entityTypes.GetProperties()
    .Concat<IPropertyBase>(entityType.GetNavigations()))
{
    // ...
}

推荐阅读