GetAllinStancesを呼び出すときに、装飾されたインスタンスの基礎となる実装タイプを発見するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/19825921

質問

私はこのコードを持っています:

using (container.BeginLifetimeScope())
{
    RenderWord instruction = new RenderWord();
    var instances = container.GetAllInstances<IInstructionHandler<RenderWord>>();
    var firstInstance = result.First();
}

instances タイプです IEnumerable<IInstructionHandler<RenderWord>>

firstInstance タイプです IInstructionHandler<RenderWord> 現実には、別のデコレーターを飾る別のデコレーターを飾るデコレーターの例です...

実行時に実際のクラス instances タイプです ContainerControlledCollection<IInstructionHandler<RenderWord>> この ContainerControlledCollection クラスは非常に有用な情報を保持しています - 基礎となる ImplementationType.

私が行く方法はありますか ContainerControlledCollection または producers[0].Value.ImplementationType 実行時に、デコレーターのチェーンの下に基本実装タイプを発見できるようにしたいからです。

役に立ちましたか?

解決

@atomarasは抽象化について良い点を持っているかもしれませんが、構成ルート内でこの情報のみを使用する場合は問題ないと思います。構成ルートはシステム内のすべての実装をすでに認識しているためです。

この情報にアクセスする方法はいくつかあると思います。

  1. 使用 DecoratorPredicateContext に提供される情報 RegisterDecorator 拡張方法:

    var typeMapping = new Dictionary<Type, Type>();
    
    container.RegisterDecorator(typeof(IInstructionHandler<>), typeof(FakeDecorator<>), c =>
    {
        typeMapping[c.ServiceType]  = c.ImplementationType;
        // or perhaps even use c.AppliedDecorators property to see which decorators 
        // are applied.
    
        // return false to prevent the decorator from being applied.
        return false;
    });
    

    簡単なインジェクターがすべてを呼び出すという偽の登録を行うことができます IInstructionHandler<T> システム内では、常に戻ってくる述語を提供することによってそれが適用されるのを防ぎます false. 。単純なインジェクターが提供する情報を使用することができます DecoratorPredicateContext 実際の実装タイプが何であるかを確認します。

または、ANを注入することもできます DecoratorContext インスタンス(v2.6以降)が最も多くのデコレーターに(説明されているように) ここ)。 DecoratorContext と同じ情報が含まれています DecoratorPredicateContext そうですが、このオブジェクトは、単純なインジェクターによって自動的に注入されます。これにより、デコレーター内で決定を下すことができます。これは、あなたの場合に非常に便利かもしれません。

  1. anを追加します IDecorator システムへの抽象化により、デコレーターチェーンを横断することができます。

    各デコレーターにaを実装させることにより IDecorator decoreeeへのアクセスを可能にするインターフェイス(完了したとおり ここ)デコレーターチェーンを通過して、実際の実装タイプを見つけることができます。

    public interface IDecorator
    {
        object Decoratee { get; }
    }
    
    public static class DecoratorHelpers
    {
        public static IEnumerable<object> GetDecoratorChain(IDecorator decorator)
        {
            while (decorator != null)
            {
                yield return decorator;
    
                decorator = decorator.Decoratee as IDecorator;
            }
        }
    }
    

    次のように、このインターフェイスでデコレーターを実装できます。

    public class SomeDecorator<T> : IInstructionHandler<T>, IDecorator
    {
        private readonly IInstructionHandler<T> decoratee;
    
        public SomeDecorator(IInstructionHandler<T> decoratee)
        {
            this.decoratee = decoratee;
        }
    
        object IDecorator.Decoratee { get { return this.decoratee; } }
    }
    

    すべてのデコレーターにこのインターフェイスを実装すると、これを行うことができます。

     var implementationTypes =
         from handler in container.GetAllInstances<IInstructionHandler<RenderWord>>()
         let mostInnerDecorator =
             DecoratorHelpers.GetDecoratorChain(handler as IDecorator).LastOrDefault()
         let implementation = mostInnerDecorator != null ? mostInnerDecorator.Decoratee : handler
         select implementation.GetType()
    
  2. のリストを登録します Registration の1つのインスタンス RegisterAll 以来 Registration オブジェクトは、実際の実装タイプを知っています。

  3. ただし、ポイント3の代わりに、それらの登録を作成するために使用したインプレメーションタイプのリストを使用することもできます。

    typeMapping[serviceType] = implementationTypes;
    container.RegisterAll(serviceType, implementationTypes);
    

    単純なインジェクターは、登録された実装を常に登録しているのと同じ順序で解決します(これが保証されます)。したがって、物事のコレクションを解決すると、同じ順序でレイアウトされた実装のリストが既にあります。

他のヒント

なぜfirst Instanceのタイプをチェックしないのですか?それはあなたに実際の実装タイプを与えませんか?ただし、実装タイプを知る必要があるという事実は、抽象化の問題の適切な兆候であると言わざるを得ません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top