0

WinFormsタブ付きMDIインターフェイスを使用してC#でLOBアプリケーションに取り組んでいます。DataGridViewsにはさまざまなフォームがあり、ユーザーが関心のあるオブジェクトを選択して、新しいフォームで表示/編集できるようになっています。

私の主なビジネスオブジェクトはそれぞれ、以下のように定義されているEntityを継承しています。

public abstract class Entity
{
    public static event Action Saved;

    internal virtual void OnSaved()
    {
        if (Saved != null)
        {
            Saved();
        }
    }
}

次に、グリッドにデータを取り込むオブジェクトがあります(これらは、実際にはLinqからSQLに自動生成されたクラスですが、通常のクラスで問題を再現できます)。

class Class1 : Entity
{
    //Stuff
}


class Class2 : Entity
{
    //Stuff
}

特定のクラスのオブジェクトがいつ変更されるかを知りたいのですが、グリッドを更新して他のアクティビティを実行できるように、どのインスタンス(したがって静的アクション)を気にしません。

問題は、イベントが派生クラスインスタンスから発生したときに発生します。他のすべての派生クラスに対しても発生します。例えば:

Class1.Saved += new Action(s1);
Class2.Saved += new Action(s2);

private void TestIt()
{
    Class2 o2 = new Class2();
    o2.OnSaved();  
}

これはs1とs2を起動しますが、特定の1つ(つまりs2)のみを起動する必要があります。これを行うための最良の方法は何ですか?この動作を必要とするクラスがかなりあり、可能であれば各クラスにコードを追加する必要はありません。

アップデート:

たくさんのご回答ありがとうございました。とても参考になりました。

私は少し異なるオプションを選択しました。これはかなりハッキーに思えますが、私の目的にはうまく機能します。これには、アクションでタイプを渡し、ハンドラーにフィルターをかけて関連する操作を呼び出させることが含まれます。

エンティティクラス:

public abstract class Entity
{
    public static event Action<Type> Saved;


    internal void OnSaved()
    {
        private Action<Type> SavedCopy = Saved;        

        if (SavedCopy != null)
            SavedCopy(this.GetType());
    }
}

ハンドラーを接続します:

 Entity.Saved += new Action<Type>(Handler);

ハンドラーメソッドの例(これはフォームごとに異なります):

    void Handler(Type obj)
    {
       if (obj==typeof(Class1))
           UpdateGrid();
       else if (obj==typeof(Class2))
           UpdateBasicInfo();
       else if (obj == typeof(Class3))
           DoAnotherThing();
    }
4

4 に答える 4

1

ジェネリックを使用すると、回避策になる可能性があります。各ジェネリック クラスは静的フィールドのコピーを取得します。

public abstract class Entity<T>
{
    public static event Action Saved = delegate { };

    internal virtual void OnSaved()
    {
        Saved();
    }
}

class Class1 : Entity<Class1>
{
    //Stuff
}

class Class2 : Entity<Class2>
{
    //Stuff
}
于 2012-05-09T08:50:08.183 に答える
0

イベントが基本型で定義されている場合、デリゲートが登録されている型を特定できないため、型ごとにイベントが必要になります。

public abstract class Entity
{
    internal abstract void OnSaved();
}

class Class1 : Entity
{
    public static event Action Saved = () => { };

    internal override void OnSaved()
    {
        this.Saved();
    }

    //Stuff
}

class Class2 : Entity
{
    public static event Action Saved = () => { };

    internal override void OnSaved()
    {
        this.Saved();
    }

    //Stuff
}
于 2012-05-08T11:15:09.017 に答える
0

このようにするのが良い考えかどうかはわかりませんが、サブスクライブするときとデータを保存するときにタイプを指定できます。

public abstract class Entity
{
    private static Dictionary<Type, Action> Subscribers
         = new Dictionary<Type, Action>();

    internal virtual void OnSaved()
    {
        OnSaved(GetType());
    }

    private OnSaved(Type type)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        if (subscribed != null)
            subscribed();
    }

    public Subscribe(Type type, Action action)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        Subscribers[type] = subscribed + action;
    }

    public Unsubscribe(Type type, Action action)
    {
        Action subscribed;
        Subscribers.TryGetValue(type, out subscribed);
        Subscribers[type] = subscribed - action;
    }
}

このコードはスレッドセーフではないことに注意してください。異なるスレッドから同時に使用する場合は、ロックを追加する必要があります。

于 2012-05-08T12:22:55.037 に答える
0

なぜ静的でなければならないのですか?代わりにインスタンス イベントにします。

public event Action Saved;

クラスごとに1回(または、現在の場合は1回)ではなく、インスタンスごとに接続する必要がありますが、イベントが分離されます。

于 2012-05-08T12:32:30.103 に答える