4

MVC Web API パイプラインで処理されているIHttpControllerActivatorコントローラーに依存するコントローラーの依存関係を解決できるように、with StructureMapのインターフェイスの実装を構築しようとしています。HttpRequestMessage

私の実装Createは次のとおりです。

public IHttpController Create(
    HttpRequestMessage request,
    HttpControllerDescriptor controllerDescriptor,
    Type controllerType)
{
    return (IHttpController)this.Container
        .With(request)
        .With(controllerDescriptor)
        .GetInstance(controllerType);
}

Containerプロパティは、IContainer構築時にアクティベーターに渡される StructureMap インスタンスへの参照です。

コントローラーの登録では、リフレクションを使用してすべてのApiController実装を取得します。

foreach(var controller in this.GetType().Assembly.GetTypes()
    .Where(type => typeof(ApiController).IsAssignableFrom(type)))
{
   this.For(controller).Use(controller);
}

デバッガーを使用して、コントローラー インスタンスを初期化し、それらの依存関係を渡すことを確認しました。ただし、ExecuteAsyncメソッドがコントローラーで呼び出されると、例外がスローされます。

「ApiController」インスタンスを再利用できません。「ApiController」は、着信メッセージごとに構築する必要があります。カスタム 'IHttpControllerActivator' をチェックして、同じインスタンスを作成しないことを確認してください。

掘り下げて実験した後、これは、値が割り当てられているかどうかを確認するために のプロパティExecuteAsyncをチェックする開始時に実行されるチェックによるものであることがわかりました。プロパティの値が null 以外の場合、コントローラーが要求の処理に既に使用されていると推測し、操作を中止します。RequestApiController

これに加えて、StructureMap がコントローラーの作成時にセッター注入動作を使用しようとしており、Requestnull 以外の値を持つ責任があることを確認しました。

私のレジストリでは、setter-injection を構成していないので、なぜここで呼び出されるのか混乱しています。StructureMap API を調べてみても、表示された動作を変更する方法について明確な答えは得られませんでした。

StructureMap を間違って呼び出していますか? 「プロパティ値を決して割り当てない」と言うために活用できる構成設定はありますか?

4

1 に答える 1

0

あなたの問題は、あなたがコントローラーを設定している方法を中心に展開していると思いますStructureMap. これを正しく機能させるための最善の方法は、独自のIDependencyResolver. これのかなり良い例がhttp://craigsdevspace.wordpress.com/2012/02/26/using-structuremap-with-web-api/にあります。

ただし、基本的なコードは次のようになります。

IDependencyResolver :

public class _DependencyResolver : _DependencyScope, IDependencyResolver {

    public _DependencyResolver(IContainer container) : base(container) { }

    public IDependencyScope BeginScope() {
        return new _DependencyScope(_container);
    }
}

IDependencyScope :

public class _DependencyScope : ServiceLocatorImplBase, IDependencyScope {
    protected readonly IContainer _container;

    public _DependencyScope(IContainer container) {
        if (container == null)
            throw new ArgumentNullException("container");

        _container = container;
    }

    public override object GetService(Type serviceType) {
        if (serviceType == null)
            return null;

        try {
            return (serviceType.IsAbstract || serviceType.IsInterface)
                ? _container.TryGetInstance(serviceType)
                : _container.GetInstance(serviceType);
        } catch {
            return null;
        }
    }

    protected override object DoGetInstance(Type serviceType, string key) {
        if (string.IsNullOrEmpty(key))
            return _container.TryGetInstance(serviceType);

        return _container.TryGetInstance(serviceType, key);
    }

    protected override IEnumerable<object> DoGetAllInstances(Type serviceType) {
        return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
    }

    public void Dispose() {
        //_container.Dispose();
    }

}

これらのクラスを WebAPI に接続するには、以下を に追加しますGlobal.asax

GlobalConfiguration.Configuration.DependencyResolver = 
    new _DependencyResolver(ObjectFactory.Container);

そして、Global.asaxまたはあなたの のいずれかにBootstrapper、次を追加します。

ObjectFactory.Initialize(x => {
    x.Scan(scanner => scanner.AddAllTypesOf<ApiController>());
});

StructureMapこれにより、スタックの既存の注入構造を使用するように実装が設定されます。これにより、発生している問題を回避できます。

于 2013-02-28T21:08:23.970 に答える