首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试在IInterceptor中从Ninject解析项失败

尝试在IInterceptor中从Ninject解析项失败
EN

Stack Overflow用户
提问于 2014-05-04 04:01:29
回答 2查看 440关注 0票数 0

我正试图在我目前的项目中使用尼尼特,到目前为止,我一直很喜欢它。我正在尝试配置一个IInterceptor对象,以拦截和处理对服务层的失败的方法调用。这是托管在一个ASP.NET MVC 5应用程序中。

IInterceptor中,我尝试了几种方法,例如:

  1. 使用构造函数注入来设置私有变量,但后来发现它似乎将为方法无限期地重用IInterceptor实例,而且我还没有找到阻止这种情况的方法。因为我引入范围的事情之一是一个DbContext,它会在其他地方被释放,因此它最终在任何未来的请求上失败,而不是创建它的请求。
  2. 我发现IInvocation有一个Request.Kernel属性。但是,当我试图从容器(即.InRequestScope() )解析UOW时,它失败了,因为它试图解析IUowService依赖项(其中一个依赖项依赖于此时为null的HttpContext ),但它似乎是在请求范围之外这样做的。它忽略了一个事实,即它所需要的依赖项已经在ASP.NET请求中创建,并且正在尝试创建新的依赖项。
  3. 为拦截器this.Bind<NinjectExceptionHandler>().ToSelf().InTransientScope()设置绑定,但这似乎并没有停止拦截器的缓存。

我想我错过了什么。我理解想要缓存IInterceptor对象以提高性能,但我发现很难轻松地使用IOC容器或注入来获取我的请求所需的对象。

这是我与拦截和运行的最后一个问题,因为我需要,所以任何帮助都是非常感谢的!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-04 12:38:45

因此,似乎没有办法做我所尝试的那样优雅地与尼尼姆。一旦进入IInterceptor和异步操作的后期部分,HttpContext就丢失了,Ninject无法解决它认为应该在范围内的事情。再加上它重用IInterceptor作为一种方法(就像我说的,可以理解,但令人恼火),我只是无法按我的意愿使它正常工作。

我所能做的只是一些简单的事情,但我觉得有点疯狂(我认为)。由于我正在拦截的所有方法都在我的服务层中,而且我的所有服务都通过一个BaseService抽象基类实现了一个BaseService,而这个类恰好有我需要的对象作为属性,所以我能够在拦截器中这样做:

代码语言:javascript
复制
var uow = (invocation.Request.Target as IBaseService).UnitOfWork;

这允许我访问我的工作单元并失败,以及访问我正在处理的日志实例。

虽然这样做有效,但我希望看到通过多个调用使拦截器构造函数注入正确工作,或者通过对内核的进一步调用来了解它已经解析了一个仍在作用域中的对象(尽管我猜测它可能会因为ASP.Net在等待时放弃了作用域而认为它超出了作用域)。

对于任何感兴趣的人,我将尝试在我的博客上张贴这方面的内容(如果我真正感兴趣的话,请看我的用户页面,而不是自己发垃圾邮件)。

票数 0
EN

Stack Overflow用户

发布于 2014-05-04 13:47:25

根据您的请求,我将详细介绍如何实现"1代理:1拦截器“实例关系。

我们采用了一种简单的方式,它提供的灵活性不如官方的九目标拦截扩展提供的灵活性。我们直接依赖于castle.core动态代理,因此城堡的IInvocation接口。

(请不要为没有目标的代理编写下面的代码,但是带有目标的代理非常相似--唯一改变的是您需要知道目标类类型并使用IResolutionRoot.Get<TargetClassType>()实例化它)。

基本上,我们创建了一个绑定,例如:

代码语言:javascript
复制
IBindingRoot.Bind<IFoo>()
     .ToProvider<InterfaceProxyWithoutTargetProvider<IFoo>>();

当然,现在我们需要知道代理将使用哪些拦截器。我们再一次使用了一种简单的--但不是很好--的设计:

代码语言:javascript
复制
public interface IInterceptorBindingDefinition<TTarget>
{ 
     Type InterceptorType { get; }
}

public class InterceptorBindingDefinition<TTarget, TInterceptor> : IInterceptorBindingDefinition<TTarget>
  where TInterceptor : IInterceptor
{
     Type InterceptorType { get { return typeof(TInterceptor); } }
}

IBindingRoot
  .Bind<IInterceptorBindingDefinition<IFoo>>()
  .To<InterceptorBindingDefinition<TTarget, LoggingInterceptor>();

IBindingRoot
  .Bind<IInterceptorBindingDefinition<IFoo>>()
  .To<InterceptorBindingDefinition<TTarget, SomeOtherInterceptor>();      

这意味着IFoo将获得两个拦截器:LoggingInterceptorSomeOtherInterceptor

以及提供者的实施:

代码语言:javascript
复制
public class InterfaceProxyWithoutTargetProvider<TInterface> : IProvider<TInterface>
    where TInterface : class
{
    private readonly IProxyGenerator proxyGenerator;
    private readonly IInterceptorFactory interceptorFactory;

    public InterfaceProxyWithoutTargetProvider(IProxyGenerator proxyGenerator, IInterceptorFactory interceptorFactory)
    {
        this.proxyGenerator = proxyGenerator;
        this.interceptorFactory = interceptorFactory;
    }

    public Type Type
    {
        get { return typeof(TInterface); }
    }

    public object Create(IContext context)
    {

         var interceptorTypes = context.Kernel.Get<IEnumerable<IInterceptorBindingDefinition<TInterface>>();

         IList<IInterceptor> interceptors = interceptorTypes
              .Select(x => x.InterceptorType)
              .Select(x => context.ContextPreservingGet(x))
              .ToList();

        return this.proxyGenerator.CreateInterfaceProxyWithoutTarget<TInterface>(interceptors);
    }
}

当然,我们稍微改进了一下,这样我们就有了一个流畅的语法,配置了代理和拦截器的绑定--这很容易。

但是,nInject.Extensions.Reception与其IAdviceRegistryIAdvice的方法当然更好(但也需要更深入地了解ninject是如何工作的)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23452457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档