我可以在部分类中定义属性,然后用另一个部分类中的属性标记它们吗?

Posted

技术标签:

【中文标题】我可以在部分类中定义属性,然后用另一个部分类中的属性标记它们吗?【英文标题】: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; 

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

【问题讨论】:

“从数据库生成”有多少?只有属性定义,还是代码? 简答,不。长答案,重复***.com/questions/456624/…。 @snemarch:仅限属性定义,我打算手动编写任何其他代码。 你能用接口+实现拆分而不是部分类吗?从数据库生成接口,在实现中实现(并添加属性)。 是的,这是可能的,但是通过使用元数据,然后让其他部分继承该元数据 【参考方案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。我认为这是一个很好的论据,可以将元类与带注释的类放在同一个文件中,甚至可能放在文件的顶部,以便其他编码人员更有可能找到该代码。

以上是关于我可以在部分类中定义属性,然后用另一个部分类中的属性标记它们吗?的主要内容,如果未能解决你的问题,请参考以下文章

部分类并双击控件

用另一个部分类覆盖部分类的默认构造函数

C#:如何为部分类中的属性设置默认值?

通过接口属性 LINQ to Entities

属性分类及其实现

部分类/部分类文件