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


82

有没有一种方法可以让我生成这样的代码文件:

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

然后在另一个文件中:

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

这样我就可以从数据库生成一个类,然后使用一个非生成的文件对其进行标记?


“从数据库生成”多少钱?仅属性定义还是代码?
snemarch

1
简短的回答,不。长答案,stackoverflow.com / questions / 456624 /…的重复
Kirk Woll 2010年

@snemarch:仅属性定义,我计划手工执行任何其他代码。
克里斯·麦考尔

1
您能用接口+实现拆分代替部分类吗?从数据库生成接口,在实现中实现(并添加属性)。
snemarch

是的,这是可能的,但是通过使用元数据,然后让其他部分继承该元数据
Cyber​​Ninja

Answers:


33

我已经在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; }
}

10
值得一提的是这个答案,但这并不是对《任择议定书》提出的问题的一般解决方案。属性的消费者仍然需要知道寻找元数据类-即,这些属性不会由Attribute.GetCustomAttribute(...)返回。(幸运的是,在许多用例中,使用者是由MS编写的,在某些情况下,它是可行的。)
Kirk Woll 2010年

1
此解决方案不能解决问题。为什么我们要装饰另一个文件中的成员?因为每次设计器运行时该类都是OVERWRITTEN的。因此[MetaDataType ...,设计师每次运行都会清除您的属性

2
@Desolator-想法是您不要将MetadataType属性放在设计人员生成的文件中,而是将其放在Person定义了局部类的另一个文件中。
Dan Dumitru

1
该解决方案的问题是班级应该是部分班级
Cyber​​Ninja

85

这是我在这种情况下一直使用的解决方案。当您具有要用属性修饰的自动生成的类时,此功能很有用。假设这是自动生成的类:

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属性的连接。做得好!
Pflugs

如果要向的构造函数添加属性UserProfile怎么办?
Botis

2
MetadataType在.NET的核心不存在
WoIIe

2
.net核心使用ModelMetadataType
YLJ

1
@Dave支持应该出现在.NET Core 3.0中
Roger Willcocks

2

这是我的答案,是
不同的类文件,或者您可以将元数据合并在同一个文件中,但要使命名空间相同。

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

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

1

您需要为您的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; }
}

0

并非如此;编译器会抱怨该成员定义为多个部分。但是,由于自定义属性的使用本质上是反射性的,因此您可以定义“元数据”类并将其包含装饰器。

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();

1
将属性添加到他或她的属性中的演员也是多久使用一次属性的人,因此会知道寻找神奇的“ Meta”类?
柯克·沃尔

根据我的经验,经常发生。这不适用于现有的面向方面的框架,但是如果您使用自定义验证属性来修饰您的域,那么您就是在寻找它们并可以定义位置。我的团队正是在我们的一个项目中做到了这一点。主要的缺点是不寻找其他人。它在开发时保持两个并行的类,一个功能,另一个装饰。如果您首先可以定义部分字段/属性,那么在部分类中也是一个问题。
KeithS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.