18

.NET のパブリック プロパティに属性を設定したいのですが、別のファイルで生成されたコードであるため、明示的なプロパティ自体にアクセスできません。

私はこのフィールドを持っています:

public virtual string Name { get; set; }

これを設定したい:

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

私のクラスは部分的としてマークされていますが、部分的なプロパティを持つことはできません。Dynamic Data と DataAnnotations の新機能である MetadataType クラスに何か引っかかっていると思っていたのですが、どうやら Dynamic Data でしか使えないように感じました。

引用: 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

4 に答える 4

23

これは既知の問題です。生成されたメンバーにメタデータを追加することはできません。

ここには 6 つのオプションがあります (労力がかかる順に):

  • 属性を所有している場合は、クラスに対して宣言できるようにします。たとえば、次のようにします。[ValidateNonEmpty("Name", "Name is required", ExecutionOrder = 1)]- 次に、複数の属性を部分クラス定義に追加します。
  • 属性を介するのではなく、仮想/インターフェース/などのメソッドを使用してこれをクエリします
  • 生成された型をサブクラスにします。メンバーをオーバーライドまたは再宣言し、メタデータを追加します (非常に面倒です)
  • カスタムTypeDescriptionProviderを使用して動的メタデータを提供します (多くの作業) - 消費者が尊重することを前提としていTypeDescriptorます。ほとんどのバインディング関連のコンシューマーはそうしていますが、たとえばExpression(多くの LINQ プロバイダーで使用されている) はそうではありません
  • コードジェネレーターを変更する/自分で書く
  • PostSharp のようなものを拡張して作業を行ってみてください (私はこれを行う方法を見つけていませんが、方法を見つけたらぜひ聞いてください!)

[DisplayName]システム定義の属性 (など)でない限り、通常は最初のオプションで成功します。が動的データで定義されている場合[ValidateNonEmpty]、これを行うことができない場合があります。

于 2009-01-19T05:54:37.173 に答える
6

生成されたクラスは部分クラスであるため、次のように動作するはずです。

  1. このプロパティが宣言されたインターフェイスを作成し、ValidateNonEmpty 属性で装飾します。
  2. AutoGenerated クラスと同じ名前で独自の部分クラスを作成し、作成したインターフェイスを実装します。
  3. プロパティはその属性で装飾されているはずです

例えば:

// 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から得ました。

于 2013-10-16T10:04:24.077 に答える
2

これは素晴らしい解決策ですが、私の問題にはうまくいきませんでした。既存のデータベースからコード ファーストで生成されたクラスで EF 6 を使用しています。テーブル内の列の 1 つは、自動生成された値を持つ IDENTITY です。ただし、生成された部分クラスは、データベースにキーを生成させるために必要な[DatabaseGenerated(DatabaseGeneratedOption.Identity)]属性を提供しませんでした。その結果、「IDENTITY_INSERT が OFF に設定されている場合、テーブル 'mytable' の ID 列に明示的な値を挿入できません。」というエラーが表示されます。私はあなたの解決策を試しましたが、うまくいきませんでした。しかし、元の生成されたクラスに属性を追加すると、機能します。そのため、自動生成されたファイルを変更する必要のない解決策を見つけようとしています。

あなたのソリューションを使用して試したコードは次のとおりです。

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; }
}
于 2014-05-07T16:24:01.993 に答える
1

別のオプションは、同じクラスの生成されていないプロパティ内にプロパティをラップすることです。二重のプロパティが発生する可能性があるため理想的ではありませんが、ジェネレータに保護されたプロパティを作成させることができれば、かなり良いアプローチになります。

この問題に対処する必要がありました。EntityFrameworkはクラスを生成します。より単純な名前で、それらを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; }
    }
} 
于 2012-11-15T04:14:06.607 に答える