0

アクションを提供し、アプリケーション ページの大部分で再利用される共通のユーザー ページ コントロールがあるとします。保存、キャンセル、リセット、送信などの一般的なアクション。現時点では約 10 個あります。

特定のアクション状態は通常、ページに表示されているエンティティとその状態に依存しますが、必ずしもそうではありません。新しいエンティティ インスタンスを作成する場合、[保存][キャンセル]を表示して有効にすることができます。しかし、既存のものを編集する場合、SaveCancel、およびResetがアクティブに表示されるアクションになる可能性があります。

アクション コモン コントロールとページ間の通信

アクションを含むこの共通コントロールは状態が分離されており、ページのコンテキスト (またはエンティティ タイプとその状態) を認識しないため、共通コントロールが使用するアクション ボタン ゲッターをページが提供できるように、インジェクション フックを与えることにしました。 .

イベントとデリゲートを定義する代わりに、ほぼ同じシナリオの単純化されたタイプを実行することにしました。プロパティを使用しましFunc<bool>たが、イベント/デリゲートに簡単に変換できます。それでも、これは現時点で定義されている方法です(送信アクションの例):

private Func<bool> DefaultState = () => false;

private Func<bool> isSendVisible;
public Func<bool> IsSendVisible
{
    private get { return isSendVisible ?? DefaultState; }
    set { isSendVisible = value; }
}

private Func<bool> isSendEnabled;
public Func<bool> IsSendEnabled
{
    private get { return isSendEnabled ?? DefaultState; }
    set { isSendEnabled = value; }
}

問題は、インターフェイス内でこれらのいくつかのプロパティを定義したことです。

public interface ISendActionProvider
{
    Func<bool> IsSendVisible { set; }
    Func<bool> IsSendEnabled { set; }
}

私の共通コントロールはこのインターフェイス (および他のアクションのインターフェイスも) を実装していますが、他のコントロール (ページ自体も含む) は同じインターフェイスを提供できるため、同じボタンを複数の場所に表示でき、同じアクション状態メカニズムが再利用されます。アクションプロバイダーがアクションの状態を適切に設定できるように、ページは初期化中にゲッターをプロバイダーにバインドするだけで済みます。

問題

問題は、新しいアクションごとに、同じインターフェースと実装を追加する必要があり、その結果、コードがかなり重複することです。

単一のインターフェイスを持ち、アクションごとに実装して、単一のクラス (アクション プロバイダー クラス - 私の場合は、これらのアクションを提供する共通コントロール) で複数回実装できるとしたら、それは素晴らしいことです。これが C# で機能する唯一の方法は、ジェネリック インターフェイスを用意し、必要な数の実装を提供することです。しかし、複数のジェネリック インターフェイスの実装を提供するジェネリック型を区別することはできません。

public interface IActionProvider // multiple inplementations?
{
    Func<bool> IsActionVisible { set; }
    Func<bool> IsActionEnabled { set; }
}

実装が機能する方法 (上記を参照) では、すべてのアクションにデフォルトの動作が定義されていますが、特定のページでは、特定のアクションに独自のゲッターを提供して状態を提供することにより、それをオーバーライドできます。

コードを統合するにはどのような可能性がありますか?

私がしたいのは、初期化バインディング中に呼び出すことができる、ある種の汎用プロパティ プロバイダーです。

(provider as IActionProvider<TSend>).IsActionVisible<TSend> = this.IsSendVisible;

しかし、前述のように、私はそのような差別化されたジェネリック型を持っていません。

4

2 に答える 2

0

1つの可能な解決策

:私はこの質問に自分で答えていますが、私は本当に好きではないが、必要なことを実行する可能性のある解決策を持っています。私はまだより良い提案を待っています。

複数のインターフェースとその実装を使用する代わりに、定義が少し異なる1つだけを使用できます。

public interface IActionProvider
{
    void SetVisibleGetter(ActionType type, Func<bool> getter);
    void SetEnabledGetter(ActionType type, Func<bool> getter);
}

そして、実装は、個々のアクションタイプに対してある種の辞書を使用できます。

private IDictionary<ActionType, Func<bool>> isActionVisible = new Dictionary<ActionType, Func<bool>> {
    { ActionType.Cacel, AlwaysFalse }
    { ActionType.Send, AlwaysFalse },
    ...
};

public void SetVisibleGetter(ActionType type, Func<bool> getter)
{
    this.isActionVisible[type] = getter ?? this.isActionVisible[type];
}

...

次に、アクションの状態を次のように設定する必要があるアクションプロバイダーコントロール内で使用します。

linkSend.Visible = this.isActionVisible[ActionType.Send]();
于 2013-01-29T13:27:44.623 に答える
0

デフォルトの実装を提供し、継承を使用してデフォルトの実装をオーバーライドできます。

例えば

public class SubmitActionProvider:ActionProvider
{        
    public override Func<bool>  IsActionVisible
    {
         get 
         { 
            Console.WriteLine("submit");
                  return null;
         }
    }
}

public class CancelActionProvider : ActionProvider
{
    public override Func<bool> IsActionVisible
    {
        get
        {
            Console.WriteLine("cancel");
            return null;
        }
    }
}


public class ActionProvider
{
    public virtual Func<bool> IsActionVisible { get { Console.WriteLine("Default implementation"); return null; } }
    public virtual Func<bool> IsActionEnabled { set { } }
}
于 2013-01-29T13:51:12.157 に答える