18

我希望在 .NET 中的公共属性上设置一个属性,但是我无权访问显式属性本身,因为这是在另一个文件中生成的代码。

我有这个领域:

public virtual string Name { get; set; }

我想设置这个:

[ValidateNonEmpty("Name is required", ExecutionOrder = 1)]
public virtual string Name { get; set; }

我的课程被标记为部分,但你不能有部分属性。我以为我正在使用 MetadataType 类,它是动态数据和 DataAnnotations 的一个新功能,但是我觉得它只能与动态数据一起使用,这是真的吗?

引文: http: //blogs.oosterkamp.nl/blogs/jowen/archive/2008/10/16/metadatatype-attribute.aspx http://blogs.msdn.com/davidebb/archive/2008/06/16/dynamic -data-and-the-related-metadata-class.aspx

有什么方法可以设置这个属性(甚至通过 web.config!)而不接触代码生成的类?

在此先感谢,格雷厄姆

4

4 回答 4

23

这是一个已知的麻烦。您根本无法将元数据添加到生成的成员。

这里有 6 个选项(按努力增加的顺序):

  • 如果您拥有该属性,则可以针对该类声明它,例如:[ValidateNonEmpty("Name", "Name is required", ExecutionOrder = 1)]- 然后将多个属性添加到部分类定义中
  • 使用 virtual/interface/etc 方法来查询这个,而不是通过属性
  • 子类化生成的类型;覆盖或重新声明成员,添加元数据(真的很乱)
  • 使用自定义TypeDescriptionProvider提供动态元数据(大量工作) - 假设消费者尊重TypeDescriptor;大多数与绑定相关的消费者都这样做,但例如,Expression(许多 LINQ 提供者使用)没有
  • 更改代码生成器/编写自己的
  • 尝试扩展 PostSharp 之类的东西来完成这项工作(我还没有找到这样做的方法,但我很想听听你是否找到方法!)

我通常会成功使用第一个选项,除非它是系统定义的属性([DisplayName]等)。如果[ValidateNonEmpty]由动态数据定义,那么您可能无法做到这一点。

于 2009-01-19T05:54:37.173 回答
6

由于生成的类是一个部分类,以下应该可以工作:

  1. 创建一个在其中声明此属性的接口,并使用 ValidateNonEmpty 属性对其进行装饰。
  2. 创建您自己的与 AutoGenerated 类同名的分部类,并使其实现您刚刚创建的接口。
  3. 该属性现在应该使用该属性进行装饰

例如:

// Decorate the properties with attributes as required
public interface IMyInterface
{
    [ValidateNonEmpty("Name is required")]
    string Name { get; set; }
}

// This is the partial class I created, that implements the interface
public partial class MyGeneratedClass : IMyInterface
{    
}

// This is the auto-generated class
public partial class MyGeneratedClass
{
    public virtual string Name { get; set; }
}

我从geekswithblogs得到这个想法。

于 2013-10-16T10:04:24.077 回答
2

这是一个很好的解决方案,但它对我的问题不起作用。我将 EF 6 与现有数据库中的代码优先生成的类一起使用。表中的一列是具有自动生成值的 IDENTITY。但是,生成的部分类没有提供让数据库生成密钥所需的[DatabaseGenerated(DatabaseGeneratedOption.Identity)]属性。结果是错误“当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'mytable' 中插入标识列的显式值。 ”。我尝试了您的解决方案,但没有奏效。但是,如果我将属性添加到原始生成的类中,它确实有效。所以我仍在尝试寻找不需要修改自动生成文件的解决方案。

这是我尝试使用您的解决方案的代码:

public interface IMyTable
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    int ID { get; set; }
}

public partial class MyTable : IMyTable
{
}

原始生成代码:

[Table("MyTable")]
public partial class MyTable
{
    [Key]
    [Column(Order = 1)]
    public int ID { get; set; }
}
于 2014-05-07T16:24:01.993 回答
1

另一种选择是将属性包装在同一类中的非生成属性中。不理想,因为您最终可能会拥有双重属性,但如果您可以让生成器生成受保护的属性,那将是一个非常好的方法。

只需要处理这个问题:实体框架生成类,我想用更简单的名称将它们序列化为 JSON。

// GENERATED BY EF
public partial class ti_Users
{
    public ti_Users()
    {
        this.ti_CardData = new HashSet<ti_CardData>();
        this.ti_Orders = new HashSet<ti_Orders>();
    }

    protected int userId { get; set; }
    protected string userName { get; set; }
    protected string userEmail { get; set; }
    protected string userPassHash { get; set; }
    protected Nullable<System.DateTime> userLastLogin { get; set; }
    protected string userLastIP { get; set; } 

    public virtual ICollection<ti_CardData> ti_CardData { get; set; }
    public virtual ICollection<ti_Orders> ti_Orders { get; set; }
}

和附加类:

[JsonObject(memberSerialization: MemberSerialization.OptIn)]
public partial class ti_Users
{
    [JsonProperty]
    public int UserId
    {
        get { return this.userId; }
        set { this.userId = value; }
    }

    [JsonProperty]
    public string Name
    {
        get { return this.userName; }
        set { this.userName = value; }
    }

    [JsonProperty]
    public string Email
    {
        get { return this.userEmail; }
        set { this.userEmail = value; }
    }

    [JsonProperty]
    public string PassHash
    {
        get { return this.userPassHash; }
        set { this.userPassHash = value; }
    }
} 
于 2012-11-15T04:14:06.607 回答