【问题标题】:attribute on virtual property not showing via reflection虚拟属性上的属性未通过反射显示
【发布时间】:2015-08-05 19:27:41
【问题描述】:

我有一个带有属性的 EntityFramework 模型,我用它来验证字段。

private person tipProvider;
[Required]
[ForeignKey("TipProviderId")]
public virtual person TipProvider
{
    get { return tipProvider; }
    set
    {
        tipProvider = value;
        ValidateProperty(MethodBase.GetCurrentMethod().Name.Replace("set_", ""));
        raisePropertyChanged(MethodBase.GetCurrentMethod().Name.Replace("set_", ""));
    }
}

我得到PropertyInfo,然后是它的验证属性,我用它来验证属性:

public virtual void ValidateProperty(string property)
{
    errors[property].Clear();
    var propertyInfo = this.GetType().GetProperty(property);
    var propertyValue = propertyInfo.GetValue(this);
    var validationAttributes = propertyInfo.GetCustomAttributes(true).OfType<ValidationAttribute>();
    foreach (var validationAttribute in validationAttributes)
    {
        if (!validationAttribute.IsValid(propertyValue))
        {
            errors[property].Add(validationAttribute.FormatErrorMessage(string.Empty));
        }
    }
    raiseErrorsChanged(property);
}

当属性是虚拟的时,我无法通过反射找到属性。如果删除了 virtual 关键字,则会找到属性。

我真的对这种行为感到困惑。为什么不能在虚拟属性上应用属性?

【问题讨论】:

  • 尝试设置合适的 BindingFlags。喜欢:static void Main() { var method = typeof(A).GetMethod("Method", BindingFlags.Public | BindingFlags.Instance); Console.WriteLine(method.IsVirtual); var property = typeof(A).GetProperty("Property", BindingFlags.Public | BindingFlags.Instance); Console.WriteLine(property.GetGetMethod().IsVirtual); } public class A { public virtual void Method() { } public virtual string Property { get; set; } }}
  • @Frederick 没有变化,GetGetMethod().IsVirtual 和 GetSetMethod().IsVirtual 都是 true
  • 是的。但是设置了 BindingFlags 后,您就有了一个有效的 PropertyInfo 对象。这不是你要找的吗?
  • @Frederick 我之前有一个有效的 PropertyInfo 对象,只是我无法通过它找到属性
  • 您是否覆盖了派生类中的属性?

标签: c# entity-framework reflection


【解决方案1】:

我不知道你到底想做什么,但根据我从 EntityFramework 了解到的情况,问题并不完全是你的想法。您可以将属性应用于虚拟属性,并且可以通过反射毫无问题地恢复它们,就像您正在做的那样。

但是在 EF 实体上,当您将属性标记为虚拟时,您正在向 EF 定义该属性是导航属性(用于访问关系中的外键数据的属性,并且将其作为子实体检索)。

然后,当您在运行时从数据库上下文中获取此实体的新实例并访问该属性时,EF 将创建一个从您的类派生的新类(动态代理)并使用它而不是您的原始类。 Entity Framework 这样做是为了维护“延迟加载”您的关系的概念 - 避免在不需要的情况下加载整个新的依赖实体树。

因为 EF 创建了一个从您的实体派生的新类,并且该属性被它覆盖,所以您的属性没有被它继承。

您可以在this post 上查看有关虚拟标记和导航属性的更多信息。

【讨论】:

    猜你喜欢
    • 2012-08-31
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2012-12-27
    相关资源
    最近更新 更多