1

プロジェクトでこのプロパティMVVMを数え切れないほど繰り返します。これらのコード行を置き換えるジェネリック クラスまたはファクトリを作成する正しい方法は何でしょうか?

    ObservableCollection<Result> _resultCollection;
    public ObservableCollection<Result> ResultCollection
    {
        get
        {
            if (_resultCollection == null)
                _resultCollection = new ObservableCollection<Result>();
            return _resultCollection;
        }
        set
        {
            _resultCollection = value;
        }
    }
4

4 に答える 4

3

これがあなたの質問に正確に答えるわけではないことはわかっていますが、個人的には、Visual Studio で記録されたマクロを使用して、すべてを書き込んでくれることを好みます。

関連するすべてのコードを 1 か所に保持し、何が起こっているのかを簡単に理解できるため、ジェネリック クラスよりもこれを使用することを好みます。通常、私はすべてのプライベート フィールドをクラスの一番上に配置し、すべてのパブリック プロパティを#region折りたたんで保持するタグに非表示にするので、それらをスクロールする必要はありません。

VS でマクロを作成するのは非常に簡単です。[ツール] > [マクロ] > [一時マクロの記録] に移動し、キーボードのみを使用して必要な変更を実行するだけです。マクロが正しく機能したら、永久マクロとして保存します。正しく実行すれば、任意の変数でマクロを再実行でき、同じ方法でビルドされます。

マクロを作成するときに覚えておくと便利なキーボード ショートカットは次のとおりです。

  • Ctrl+C/Ctrl+Vコピー/貼り付け
  • Ctrl+Right/Ctrl+Left単語を移動する
  • Home/End行頭または行末に移動する
  • Shiftカーソルの移動に合わせて単語をハイライトします

.Replace()また、小文字を大文字に変えるなど、VB マクロ コードに若干の変更を加える必要がある場合もあります。

MVVM のすべてのパブリック プロパティを構築するために使用するマクロの例を次に示します。PRISM ライブラリを使用するため、構文を使用します。RaisePropertyChanged(() => this.SomeProperty);

Sub PRISM_BuildPropertyChanged_CursorAtDefaultAfterCtrlRE()
    DTE.ActiveDocument.Selection.LineDown(False, 2)
    DTE.ActiveDocument.Selection.WordLeft(True)
    DTE.ActiveDocument.Selection.Copy()
    DTE.ActiveDocument.Selection.LineDown(False, 3)
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.CharLeft()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "RaisePropertyChanged(() => this."
    DTE.ActiveDocument.Selection.Paste()
    DTE.ActiveDocument.Selection.Text = ");"
    DTE.ActiveDocument.Selection.LineUp()
    DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
    DTE.ActiveDocument.Selection.CharRight(False, 4)
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.CharRight()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "if (value != "
    DTE.ActiveDocument.Selection.WordRight(True)
    DTE.ActiveDocument.Selection.Copy()
    DTE.ActiveDocument.Selection.CharLeft()
    DTE.ActiveDocument.Selection.Paste()
    DTE.ActiveDocument.Selection.DeleteLeft()
    DTE.ActiveDocument.Selection.Text = ")"
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "{"
    DTE.ActiveDocument.Selection.LineDown()
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "}"
End Sub

これを使用して、次のような個人的な定義を記述できます。

private ObservableCollection<SomeObject> _someCollection;

を押してCtrl+REパブリック プロパティの定義を作成します。

private ObservableCollection<SomeObject> _someCollection;

public ObservableCollection<SomeObject> SomeCollection
{
    get { return _someCollection; }
    set { _someCollection = value; }
}

次に、マクロを実行してプロパティ変更通知を作成します

public ObservableCollection<SomeObject> SomeCollection
{
    get { return _someCollection; }
    set 
    {
        if (value != _someCollection)
        {
            _someCollection = value;
            RaisePropertyChanged(() => this.SomeCollection);
        }
    }
}

(デフォルトではCtrl+REはカーソルをプライベート フィールド定義の最後に置くため、このマクロを実行するときにカーソルを置く必要がある場所です)

値がnullかどうかをチェックするコードを追加する別の古いマクロもあり、そうであればそれをオブジェクトの新しいインスタンスに設定しますが、コンストラクターではなくコンストラクターでデフォルトの定義を設定することを好むため、これはあまり使用しませんでしたプロパティ定義で。

必要に応じて、次のようになります (マクロ名に注意してください。このマクロを実行する前に、パブリック プロパティ名を強調表示する必要があります)。

Sub CreatePublicGet_NoNull_HightlightPropertyNameFirst()
    DTE.ActiveDocument.Selection.CharLeft(False, 2)
    DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, True)
    DTE.ActiveDocument.Selection.WordRight(True)
    DTE.ActiveDocument.Selection.Copy()
    DTE.ActiveDocument.Selection.LineDown(False, 2)
    DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
    DTE.ActiveDocument.Selection.CharRight(False, 4)
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.CharRight()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.CharLeft()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.LineUp(False, 2)
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Paste()
    DTE.ActiveDocument.Selection.Text = "();"
    DTE.ActiveDocument.Selection.LineDown()
    DTE.ActiveDocument.Selection.WordLeft(True)
    DTE.ActiveDocument.Selection.CharLeft()
    DTE.ActiveDocument.Selection.WordLeft(True)
    DTE.ActiveDocument.Selection.Copy()
    DTE.ActiveDocument.Selection.LineUp(False, 2)
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "if ("
    DTE.ActiveDocument.Selection.Paste()
    DTE.ActiveDocument.Selection.Text = " == null)"
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "{"
    DTE.ActiveDocument.Selection.LineDown()
    DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.NewLine()
    DTE.ActiveDocument.Selection.Text = "}"
    DTE.ActiveDocument.Selection.LineUp()
    DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
    DTE.ActiveDocument.Selection.Paste()
    DTE.ActiveDocument.Selection.Text = " = new "
    DTE.ActiveDocument.Selection.Collapse()
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.LineDown(False, 4)
    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.LineUp(True)
    DTE.ActiveDocument.Selection.Delete()
End Sub

そして、コードは次のようになります。

public ObservableCollection<SomeObject> SomeCollection
{
    get 
    {
        if (_someCollection == null)
        {
            _someCollection = new ObservableCollection<SomeObject>();
        }
        return _someCollection; 
    }
}
于 2013-01-10T15:44:15.043 に答える
0
public abstract class XBase<T>
{
    ObservableCollection<T> _resultCollection;

    public ObservableCollection<T> ResultCollection
    {
        get
        {
            if (_resultCollection == null)
                _resultCollection = new ObservableCollection<T>();

            return _resultCollection;
        }
        set
        {
            _resultCollection = value;

        }
    }
}
于 2013-01-10T15:43:47.913 に答える
0

ええ...フィールドにバインドできるのは素晴らしいことですよね... ;-)これは私を最初の解決策に導きます:

(1) フィールドをバインドできるコンバーターを作成します。

public class FieldBindingConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var par = parameter as string;
        var field = value.GetType().GetField(par);
        return field.GetValue(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

次に、(2) XAML からフィールドを直接バインドします。

    <ItemsControl ItemsSource="{Binding ., Converter={StaticResource Field}, ConverterParameter=Coll2}" Grid.Row="1">

正直なところ、これは物事を明確にしないので、ちょっと嫌いです...したがって、2番目の解決策として、コンストラクターから直接プロパティをインスタンス化できます。

public Foo() 
{
    ResultCollection = new ObservableCollection<Result>();
}

[...]

public ObservableCollection<Result> ResultCollection { get; private set; }

これによりメモリ フットプリントが数バイト増加しますが (遅延インスタンス化のセマンティクスが直接インスタンス化に変わります)、私はそれについてあまり気にしません。

于 2013-01-11T21:10:28.707 に答える
0

私の知る限り、何らかの形式のコード生成なしでは不可能です。こちらで回答されているように、T4 テンプレートを調べてください 。

于 2013-01-10T15:31:12.013 に答える