5

次のような一連のプロパティを持つクラスがあります。

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

これらのバッキング ストアを生成するために C# 3.0 に頼ることができれば、はるかに簡単になりますが、IsDirty=true; を除外する方法はありますか? プロパティを次のように記述しても、同じ動作が得られるようにします。

[MakesDirty]
public string Name { get; set; }
4

10 に答える 10

5

いいえ。元のバージョンよりもかなり多くの(難解な?)コードを記述しないわけではありません(プロパティの属性を確認するには、リフレクションを使用する必要があります。そうでない場合は、「遅い」と言いました)。これは私が一緒に暮らせるような複製。

MSには、プロパティが変更されたときにイベントを発生させる必要があります。INotifyPropertyChangedは、変更通知の重要なインターフェイスです。私がまだ見たすべての実装は

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

可能であれば、MSの賢い人たちはすでにそのようなものを持っていると思います。

于 2008-09-15T14:55:11.483 に答える
3

コードスニペットを設定して、それらを簡単に作成できるようにすることができます。

于 2008-09-15T14:47:55.323 に答える
3

属性を使用してコードの動作を変更するために本当にそのようにしたい場合は、それを行う方法がいくつかあり、それらはすべて AOP (アスペクト指向プログラミング) に関連しています。コンパイル後のステップでコードを変更できるアフターコンパイラである PostSharp を確認してください。たとえば、オブジェクトをダーティとしてマークするプロパティ セッター内にコードを挿入するプロパティ (またはアスペクト、AOP での呼び出し方法) の 1 つのカスタム属性を設定できます。これがどのように達成されるかの例が必要な場合は、チュートリアルをチェックしてください。

ただし、AOP には注意してください。正しく使用しないと、AOP を使用して解決しようとしている問題を簡単に作成できるためです。

ポスト コンパイルを使用するものや、.Net に存在するメソッド インターセプト メカニズムを使用するものなど、より多くの AOP フレームワークがあります。

于 2008-09-15T15:12:47.650 に答える
2

いいえ、自動プロパティを使用する場合、実装を制御することはできません。最適なオプションは、テンプレートツール、コードスニペットを使用するか<T、セッターロジックをカプセル化するプライベートSetValue>(ref T backingField、T value)を作成することです。

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}
于 2008-09-15T15:00:05.607 に答える
0

他の代替手段は、プロパティの作成を自動化するcodesmithなどのコードジェネレーターです。これは、作成するプロパティがデータベーステーブルの列である場合に特に役立ちます。

于 2008-09-15T14:52:15.750 に答える
0

ContextBoundオブジェクト。コンテキストにバインドされたオブジェクトを拡張するクラスを作成し、ContextAttributeを作成すると、そのようなプロパティに対して行われた呼び出しをインターセプトしてIsDirtyを設定できます。.NETはクラスへのプロキシを作成するため、すべての呼び出しはリモートシンクなどを経由します。

ただし、このようなアプローチの問題は、プロキシが外部から呼び出された場合にのみ呼び出されることです。例を挙げましょう。

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

property1が別のクラスから呼び出されると、プロキシが呼び出されます。ただし、別のクラスがproperty2を呼び出す場合、property2のセットがproperty1を呼び出しても、プロキシは呼び出されません(クラス自体にいる場合はプロキシは必要ありません)。

ContextBoundObjectsを使用したサンプルコードはたくさんあります。調べてみてください。

于 2008-09-15T14:54:37.430 に答える
0

そのためにエンタープライズライブラリを使用することをお勧めします。Policy Application Blockは、たとえばメソッドを開始/終了するたびに「何か」(何か=自分でコーディングできます)を実行するインフラストラクチャを提供します。属性を使用して動作を制御できます。それをヒントとして、エンタープライズライブラリのドキュメントで詳細を確認してください。

于 2008-09-15T14:56:40.983 に答える
0

プロパティに割り当てることができるDefaultValueAttributeがあります。これは主にデザイナーツールによって使用されるため、プロパティが変更されたことを示すことができますが、プロパティのデフォルト値を説明する「きちんとした」方法である可能性があります。 、したがって、変更されたかどうかを識別できます。

プロパティの変更を識別するには、Reflectionを使用する必要があります。これは、多くのことを行わない限り、実際にはそれほど高価ではありません。

警告:プロパティがデフォルト以外の値からデフォルトの値に戻って変更されたかどうかを判断することはできません。

于 2008-09-15T14:59:16.297 に答える
0

これを解決する最善の方法は、アスペクト指向プログラミング(AOP)を使用することだと思います。Mats Helanderは、これについてInfoQに書き込みました。記事は少し厄介ですが、フォローすることは可能です。.NETスペースでAOPを実行するさまざまな製品がありますが、PostSharpをお勧めします。

于 2008-09-15T15:03:30.467 に答える
0

属性を使用する場合は、独自のロジックを使用して、属性の意味とその対処方法を推測する必要があると確信しています。カスタムクラスオブジェクトを使用しているものは何でも、できればインスタンス化時に、これらの属性アクション/チェックを実行する方法が必要になります。

それ以外の場合は、多分イベントの使用を検討しています。それでもすべてのsetメソッドにイベントを追加する必要がありますが、すべてのプロパティのダーティセットに対して何をするかをハードコーディングする必要がなく、何を行うかを1か所で制御できるという利点があります。それは、少なくとも、もう少しコードの再利用を導入するでしょう。

于 2008-09-15T15:08:10.067 に答える