【问题标题】:Can I define properties in partial classes, then mark them with attributes in another partial class?我可以在部分类中定义属性,然后用另一个部分类中的属性标记它们吗?
【发布时间】:2011-04-16 11:51:13
【问题描述】:

有没有办法生成这样的代码文件:

public partial class A 
{
    public string a { get; set; }
}

然后在另一个文件中:

public partial class A 
{
    [Attribute("etc")]
    public string a { get; set; }
}

这样我就可以从数据库中生成一个类,然后使用一个非生成的文件来标记它?

【问题讨论】:

  • “从数据库生成”有多少?只有属性定义,还是代码?
  • 简答,不。长答案,重复stackoverflow.com/questions/456624/…
  • @snemarch:仅限属性定义,我打算手动编写任何其他代码。
  • 你能用接口+实现拆分而不是部分类吗?从数据库生成接口,在实现中实现(并添加属性)。
  • 是的,这是可能的,但是通过使用元数据,然后让其他部分继承该元数据

标签: c# attributes code-generation partial-classes


【解决方案1】:

这是我一直用于此类情况的解决方案。当您有想要用属性装饰的自动生成的类时,它很有用。假设这是自动生成的类:

public partial class UserProfile
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

比方说,我想添加一个属性来指定 UserId 是键。然后我会在另一个文件中创建一个部分类,如下所示:

[Table("UserProfile")]
[MetadataType(typeof(UserProfileMetadata))]
public partial class UserProfile
{
    internal sealed class UserProfileMetadata
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
    }
}

【讨论】:

  • 很好的解决方案。我知道您可以使用多个文件中的属性来装饰分部类,甚至可以在其声明中添加接口和继承类,但我没有与MetadataType 属性建立联系。干得好!
  • 如果我想给UserProfile的构造函数添加属性怎么办?
  • MetadataType 在 .NET Core 中不存在
  • .net 核心使用ModelMetadataType
  • @Dave 支持应该会出现在 .NET Core 3.0 中
【解决方案2】:

我在 Scott Guthrie 的一篇文章中看到过类似的事情(接近结尾)——不过我自己没有尝试过。
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

[MetadataType(typeof(Person_Validation))]
public partial class Person
{
    // Partial class compiled with code produced by VS designer
}

[Bind(Exclude="ID")]
public class Person_Validation
{
    [Required(ErrorMessage = "First Name Required")]
    [StringLength(50, ErrorMessage = "Must be under 50 characters")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last Name Required")]
    [StringLength(50, ErrorMessage = "Must be under 50 characters")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Age Required")]
    [Range(0, 120, ErrorMessage = "Age must be between 0 and 120")]
    public int Age { get; set; }

    [Required(ErrorMessage = "Email Required")]
    [Email(ErrorMessage = "Not a valid email")]
    public string Email { get; set; }
}

【讨论】:

  • 这个答案值得一提,但这不是OP提出的问题的一般解决方案。属性的消费者仍然需要知道寻找元数据类——即这些属性将不会由 Attribute.GetCustomAttribute(...) 返回。 (幸运的是,对于许多用例,消费者是由 MS 编写的,在某些情况下这会起作用。)
  • 此解决方案不能解决问题。为什么我们要在另一个文件中装饰成员?因为每次设计器运行时该类都会被覆盖。因此,每次设计器运行时,您的属性 [MetaDataType ... 都会被清除
  • @Desolator - 这个想法是不要将MetadataType 属性放在设计器生成的文件中,而是将其放在定义了部分类Person 的另一个文件中。
  • 这个解决方案的问题是类应该是部分的
【解决方案3】:

这是我的答案
不同的类文件,或者您可以将元数据组合在同一个文件中但保持命名空间相同..这样他们就可以清楚地看到彼此。

请记住,当您更新模型时,例如添加更多列,您也必须更新项目类。

--your model class
public partial class A {
    public string a {get; set;}
}

--your project class 
public class Ametadata {
     [Attribute("etc")]
     public string a {get; set;}
}


[MetadataType(typeof(Ametadata))]
public partial class A
{
}

【讨论】:

    【解决方案4】:

    您需要为A 类定义一个部分类,就像下面的示例一样

    using System.ComponentModel.DataAnnotations;
    
    // your auto-generated partial class
    public partial class A 
    {
        public string MyProp { get; set; }
    }
    
    [MetadataType(typeof(AMetaData))]
    public partial class A 
    {
    
    }
    
    public class AMetaData
    {
        [System.ComponentModel.DefaultValue(0)]
        public string MyProp { get; set; }
    }
    

    【讨论】:

      【解决方案5】:

      不是这样的;编译器会抱怨该成员是在多个部分中定义的。但是,由于自定义属性的使用本质上是反射性的,您可以定义一个“元数据”类并使用它来包含装饰器。

      public class A
      {
         public string MyString;
      }
      
      public class AMeta
      {
         [TheAttribute("etc")]
         public object MyString;
      }
      
      ...
      
      var myA = new A();
      var metaType = Type.GetType(myA.GetType().Name + "Meta");
      var attributesOfMyString = metaType.GetMember("MyString").GetCustomAttributes();
      

      【讨论】:

      • 将属性添加到他或她的属性的演员多久也是消费他们的人,因此会知道寻找神奇的“元”类?
      • 经常,根据我的经验。这不适用于现有的面向方面的框架,但是如果您使用自定义验证属性来装饰您的域,那么您就是寻找它们的人并且可以定义它们的位置。我的团队在我们的一个项目中就是这样做的。主要缺点是不找其他类;它在开发时维护两个平行的类,一个是功能性的,另一个是装饰性的。如果您能够首先定义部分字段/属性,那么这在部分类中也是一个问题。
      • @KirkWoll 这是一个很好的问题 IMO。我认为这是一个很好的论据,可以将元类与带注释的类放在同一个文件中,甚至可能放在文件的顶部,以便其他编码人员更有可能找到该代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多