5

私の環境について説明します。Ninject + Ninject Interception Extension を使用して、特別な属性でマークされたすべてのメソッドのインターセプターの自動登録を有効にしています。これは、一般的な 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_");
    }
}
4

2 に答える 2

3

傍受の動作が変更されました。これには、メソッドが仮想である必要がなくなるという利点があるため、インターフェイスが注入されると、クラス プロキシではなく、拡張機能によってインターフェイス プロキシが作成されます。インターフェイスに配置するか、インターセプトからメソッドを除外するか(とにかく呼び出すことができないメソッドをインターセプトするのは無意味です)、インターフェイスの代わりにクラスを注入する必要があります

于 2012-04-30T23:38:32.713 に答える
1

問題はプロジェクトの git ハブに移動しました: issue

于 2012-04-30T07:29:13.820 に答える