asp.net-web-api - 如何在不调用 setter 注入(inject)的情况下丰富 StructureMap 中的对象组合?

标签 asp.net-web-api structuremap

我正在尝试使用 StructureMap 构建 IHttpControllerActivator 接口(interface)的实现,以便我可以解析依赖于 HttpRequestMessage 的 Controller 的依赖关系> 正在 MVC Web API 管道中进行处理。

我的Create实现如下:

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

Container 属性是对 StructureMap IContainer 实例的引用,该实例在构造时传递给激活器。

我对 Controller 的注册使用反射来获取所有 ApiController 实现:

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

使用调试器,我检查了 Controller 实例的初始化并传递了它们的依赖项。但是,当在 Controller 上调用 ExecuteAsync 方法时,会引发异常:

Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance.

经过一些挖掘和实验,我发现这是由于在 ExecuteAsync 开始时执行的检查所致,该检查检查 ApiControllerRequest 属性> 查看是否已被赋值。如果该属性具有非空值,则表明 Controller 已用于处理请求并中止操作。

此外,我还验证了 StructureMap 在编写 Controller 时尝试使用其 setter 注入(inject)行为,并负责 Request 具有非空值。

在我的注册表中,我没有配置任何 setter 注入(inject),所以我很困惑为什么在这里调用它。关于如何更改所表现出的行为,对 StructureMap API 的研究并没有给出任何明显的答案。

我是否错误地调用了 StructureMap?是否有一个配置设置可以用来表示“永远不要分配属性值”?

最佳答案

我认为您的问题与您使用 StructureMap 设置 Controller 的方式有关。为了使其正常工作,最好的方法是通过创建您自己的 IDependencyResolver 实现来 Hook WebAPI 堆栈的依赖项注入(inject)堆栈。 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 实现设置为使用堆栈预先存在的注入(inject)结构 - 这应该可以避免您遇到的问题。

关于asp.net-web-api - 如何在不调用 setter 注入(inject)的情况下丰富 StructureMap 中的对象组合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12646657/

相关文章:

使用 StructureMap 进行 C# 依赖注入(inject)

c# - StructureMap 和 HTTP 请求范围的服务 - 为什么我的服务在一个范围内创建了两次?

.net - StructureMap GetAllInstances 在需要多个实例时返回一个实例

c# - .NET Core API REST C# List into List is null

c# - 添加 CosmosDB 实体,(无法解析租户类型实体的 iD)

ASP.NET Core 自定义参数绑定(bind)

c# - 如何保护 ASP.NET Web API 2

c# - 使用 StructureMap 注册通用工厂的方法

asp.net - NHibernate StructureMap ASP.NET webform System.OutOfMemoryException

asp.net-mvc-4 - 通过 ViewModel 的 Microsoft Odata api 在 PATCH 中存在问题