部分クラスでプロパティを定義してから、別の部分クラスの属性でそれらをマークすることはできますか?


82

次のようなコードファイルを生成する方法はありますか?

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

そして別のファイルで:

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

データベースからクラスを生成し、生成されていないファイルを使用してマークアップできるようにするには?


「データベースから生成」はいくらですか?プロパティ定義のみですか、それともコードですか?
スネマーチ2010

1
短い答え、いいえ。長い答え、stackoverflow.com / questions / 456624 /の重複…
Kirk Woll 2010

@snemarch:プロパティ定義のみ、他のコードは手動で実行する予定です。
クリスマッコール

1
部分的なクラスの代わりに、インターフェイスと実装の分割を使用できますか?データベースからインターフェースを生成し、実装に実装(および属性を追加)します。
スネマーチ2010

はい、これは可能ですが、メタデータを使用すると、他の部分にそのメタデータを継承させる
Cyber​​Ninja 2017

回答:


33

スコット・ガスリーの記事(終わり近く)でこのようなことが行われているのを見たことがありますが、自分で試したことはありません。
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
この回答には言及が必要ですが、OPが提起した質問に対する一般的な解決策ではありません。属性のコンシューマーは、メタデータクラスを探すために知る必要があります。つまり、これらの属性はAttribute.GetCustomAttribute(...)によって返されません。(幸いなことに、多くのユースケースでは、コンシューマーはMSによって作成され、特定の状況ではこれが機能します。)
Kirk Woll 2010

1
この解決策は問題を解決しません。なぜ別のファイルでメンバーを装飾しようとするのですか?デザイナーが実行するたびにクラスが上書きされるためです。したがって[MetaDataType ...、デザイナーが実行するたびに属性がクリアされます

2
@ Desolator-MetadataType設計者が生成したファイルに属性を配置するのではなく、部分クラスPersonが定義されている他のファイルに属性を配置するという考え方です。
ダンドゥミトル2016年

1
このソリューションの問題は、クラスが部分的であるべきだったことです
Cyber​​Ninja 2017

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 2016年

のコンストラクターに属性を追加したい場合はどうなりUserProfileますか?
ボティス2017年

2
MetadataType.NETのコアには存在しません
WoIIe

2
.NETコアの使用ModelMetadataType
イル] -

1
@Daveサポートは3.0、.NETのコアでくることになっている
ロジャー・ウィルコックス

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
自分のプロパティに属性を追加しているアクターが、それらを消費している人でもあり、したがって魔法の「メタ」クラスを探すことを知っているのはどのくらいの頻度ですか?
Kirk Woll 2010

私の経験では、かなり頻繁に。これは既存のアスペクト指向フレームワークでは機能しませんが、たとえばカスタム検証属性でドメインを装飾している場合は、それらを探しているのはあなたであり、場所を定義できます。私のチームは、私たちのプロジェクトの1つでまさにこれを実行しました。主な欠点は、他のクラスを探していないことです。開発中は、機能的なクラスと装飾的なクラスの2つの並列クラスを維持しています。そもそも部分的なフィールド/プロパティを定義できれば、それは部分的なクラスでも問題になります。
キースS 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.