【发布时间】:2012-04-29 17:07:06
【问题描述】:
我将描述我的环境:我有 Ninject + Ninject 拦截扩展,用于为所有方法启用拦截器的自动注册,并标有特殊属性。是常见的AoP+属性+DI容器场景。
我的问题是: 当移植到最新版本的 Ninject 和 Ninject Interception Extension - 3.0 时,当我的拦截器应该运行时,我开始遇到异常。在解析属性类型和注册拦截器时,我的 InterceptorRegistrationStrategy 工作正常。但是运行被拦截的方法会导致以下异常:
System.ArgumentException : Interface not found.
at System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle)
at System.RuntimeType.GetInterfaceMap(Type ifaceType)
at Ninject.Extensions.Interception.Advice.Advice.MatchesMethod(IProxyRequest request)
at System.Linq.Enumerable.WhereListIterator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList(IEnumerable`1 source)
at Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptorsForRequest(IProxyRequest request)
at Ninject.Extensions.Interception.Registry.AdviceRegistry.GetInterceptors(IProxyRequest request)
at Ninject.Extensions.Interception.Wrapper.StandardWrapper.CreateInvocation(IProxyRequest request)
at Ninject.Extensions.Interception.Wrapper.DynamicProxyWrapper.Intercept(IInvocation castleInvocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Infrastructure.Tests.Persistance.Conversations.NinjectConversationInterceptorBehavior.ShouldCreateInterceptorOnImplicitConversation() in NinjectConversationInterceptorBehavior.cs: line 74
我不得不求助于 Reflector 并使用 Ninject Interception Extension 源来解决这个问题,再加上没有足够的文档,这让我处于不利的境地。
有人在移植到 Ninject 3.0 时遇到同样的异常吗?
这是我用来根据属性自动注册拦截器的代码:
public class NinjectConversationInterceptorRegistrationStrategy : InterceptorRegistrationStrategy
{
public NinjectConversationInterceptorRegistrationStrategy(IAdviceFactory adviceFactory,
IAdviceRegistry adviceRegistry)
: base(adviceFactory, adviceRegistry)
{
}
public override void Execute(IPlan plan)
{
var pcAttribute = plan.Type.GetOneAttribute<PersistenceConversationalAttribute>();
if (pcAttribute != null)
{
if (pcAttribute.MethodsIncludeMode == MethodsIncludeMode.Implicit)
{
foreach (var mi in GetCandidateMethods(plan.Type))
{
RegisterMethodInterceptors(plan.Type, mi);
if (!plan.Has<ProxyDirective>())
{
plan.Add(new ProxyDirective());
}
}
}
else
{
foreach (
var mi in
GetCandidateMethods(plan.Type).Where(
mi => mi.HasAttribute<PersistenceConversationAttribute>()))
{
if (!mi.IsVirtual)
{
throw new InvalidOperationException(
string.Format("[PersistentCoversation] attribute used on non-virtual method {0}.{1}",
mi.DeclaringType.Name,
mi.Name));
}
RegisterMethodInterceptors(plan.Type, mi);
if (!plan.Has<ProxyDirective>())
{
plan.Add(new ProxyDirective());
}
}
}
}
}
protected virtual void RegisterMethodInterceptors(Type type, MethodInfo method)
{
IAdvice advice = this.AdviceFactory.Create(method);
advice.Callback = GetIntercepor;
this.AdviceRegistry.Register(advice);
}
protected virtual IInterceptor GetIntercepor(IProxyRequest arg)
{
var interceptor = new NinjectConversationLazyInterceptor(arg.Kernel);
return interceptor;
}
protected override bool ShouldIntercept(MethodInfo methodInfo)
{
if (IsPropertySetter(methodInfo))
{
return false;
}
var ret = base.ShouldIntercept(methodInfo);
return ret;
}
private static bool IsPropertySetter(MethodBase methodInfo)
{
return methodInfo.IsSpecialName && methodInfo.Name.StartsWith("set_");
}
}
【问题讨论】:
-
更新 - 我正在通过它实现的接口解析在它周围有拦截器的类型,看起来解析 by 接口是这个异常的罪魁祸首。我不完全确定,但我认为代码行 - “InterfaceMapping interfaceMap = this.method.DeclaringType.GetInterfaceMap(request.Method.DeclaringType);”在 Advice 类中是异常的来源,更准确地说是它的参数。
-
请在 github 上添加一个错误报告,并附上一个演示问题的项目。
-
我做了一个简化的测试项目,效果很好。看起来这是我在生产中使用的组件的集成问题。我将在更多调试生产代码时更新或关闭此问题。
-
我发现了问题。拦截类型的基类有一个方法,该方法不是拦截类型实现的接口的成员。尽管基类的这种方法被隐式注册以进行拦截。我不知道这是否是一个错误。虽然它在以前的版本中工作。测试项目链接:ge.tt/4bqPYbG/v/0?c
标签: ninject aop interceptor ninject-extensions ninject-interception