将属性与.net中的代码生成属性相关联

时间:2009-01-19 05:36:26

标签: .net attributes code-generation

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

我有这个字段:

public virtual string Name { get; set; }

我希望这样做:

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

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

引用: 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-associated-metadata-class.aspx

有没有办法在不触及代码生成类的情况下设置这个属性(即使是通过web.config!)?

提前致谢, 格雷厄姆

4 个答案:

答案 0 :(得分:23)

这是一个众所周知的滋扰;您根本无法向生成的成员添加元数据。

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

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

我通常使用第一个选项取得成功,除非它是系统定义的属性([DisplayName]等)。如果[ValidateNonEmpty]由动态数据定义,那么您可能无法执行此操作。

答案 1 :(得分:6)

由于生成的类是部分类,因此以下内容应该起作用:

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

    例如:

    // 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得到了这个想法。

答案 2 :(得分:2)

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

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

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; }
}

答案 3 :(得分: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; }
    }
}