6

SimpleInjector を IOC コンテナとして使い始めようとしていますが、今のところ満足しています。しかし今、私は解決できない問題に行き詰まっています。SOとドキュメントで検索しましたが、まだ回答がないようです。SimpleInjector のハウツー ドキュメントを見たことがありますが、オープン ジェネリック インターフェイスについては触れていません。

次のような 2 つの汎用インターフェイスがあります。

public interface IEventPublisher<TEvent>
{
   void Publish(TEvent Event);
}
public interface IEventSubscriber<TEvent>
{
    void Subscribe(Action<TEvent> CallBack);
}

そして、これら 2 つのオープン ジェネリック実装が 1 つあります。

class EventMediator<T> : IEventPublisher<T>, IEventSubscriber<T>
{
    List<Action<T>> Subscriptions = new List<Action<T>>();

    public void Publish(T Event)
    {
        foreach (var Subscription in this.Subscriptions)
            Subscription.Invoke(Event);
    }

    public void Subscribe(Action<T> CallBack)
    {
        this.Subscriptions.Add(CallBack);
    }
}

私のアプリケーションでは、SimpleInjector を次のように設定しています。

this.Container = new SimpleInjector.Container();
this.Container.RegisterOpenGeneric(typeof(IEventPublisher<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.RegisterOpenGeneric(typeof(IEventSubscriber<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.Verify();

私がアーカイブしようとしているのは、IEventPublisher または IEventSubscriber を要求するときに、まったく同じインスタンスを取得したいということです。さらに、このインスタンスは、任意の T のシングルトンになります。

私はこれらの行でこれをテストしました:

class DummyEvent {}

var p = this.Container.GetInstance<IEventPublisher<DummyEvent>>();
var s = this.Container.GetInstance<IEventSubscriber<DummyEvent>>();
var areSame = (object.ReferenceEquals(p,s));

残念ながら、 p と s は同じインスタンスを参照していません。誰でもこの問題の解決策を知っていますか?

4

2 に答える 2

3

IEventPublisherIEventSubscriberを別々のシングルトンとして登録しています。何らかの方法でコードをリファクタリングする必要があります。1 つの解決策は、仲介者の 3 つの責任を分離することです。

サブスクライバー

public interface IEventSubscriber<TEvent>
{
    void Subscribe(Action<TEvent> CallBack);
}

public class EventSubscriber<T> : IEventSubscriber<T>
{
    public readonly ISubscriptions<T> subscriptions;

    public EventSubscriber(ISubscriptions<T> subscriptions)
    {
        this.subscriptions = subscriptions;
    }

    public void Subscribe(Action<T> CallBack)
    {
        this.subscriptions.Add(CallBack);
    }
}

パブリッシャー_

public interface IEventPublisher<TEvent>
{
    void Publish(TEvent Event);
}

public class EventPublisher<T> : IEventPublisher<T>
{
    public readonly ISubscriptions<T> subscriptions;

    public EventPublisher(ISubscriptions<T> subscriptions)
    {
        this.subscriptions = subscriptions;
    }

    public void Publish(T Event)
    {

        foreach (var subscription in this.subscriptions)
        {
            subscription.Invoke(Event);
        }
    }
}

サブスクリプション

public interface ISubscriptions<T> : IList<Action<T>> { }

public class Subscriptions<T> : List<Action<T>>, ISubscriptions<T> { }

サブスクリプションのみをシングルトンとして登録する必要があります

var container = new Container();
container.RegisterOpenGeneric(typeof(IEventSubscriber<>), typeof(EventSubscriber<>));
container.RegisterOpenGeneric(typeof(IEventPublisher<>), typeof(EventPublisher<>));
container.RegisterSingleOpenGeneric(typeof(ISubscriptions<>), typeof(Subscriptions<>));
container.Verify();

var p = container.GetInstance<IEventPublisher<DummyEvent>>();
var s = container.GetInstance<IEventSubscriber<DummyEvent>>();
Assert.That(
    (p as EventPublisher<DummyEvent>).subscriptions  == 
    (s as EventSubscriber<DummyEvent>).subscriptions);
于 2014-06-27T13:59:58.993 に答える