Ninject 拦截任何具有特定属性的方法吗?

发布于 2024-11-15 19:54:10 字数 393 浏览 6 评论 0原文

我怎样才能让 Ninject.Extensions.Interception 基本上让我将特定的拦截器绑定到具有属性的任何方法... psudocode:

Kernel.Intercept(context => context.Binding.HasAttribute<TransactionAttribute>())
      .With<TransactionInterceptor>

使用如下类:

public SomeClass
{
    [TransactionAttribute]
    public void SomeTransactedMethod()
    { /*do stuff */ }
}

How can I get Ninject.Extensions.Interception to basically let me bind a specific interceptor to any method that has an attribute... psudocode:

Kernel.Intercept(context => context.Binding.HasAttribute<TransactionAttribute>())
      .With<TransactionInterceptor>

With a class like:

public SomeClass
{
    [TransactionAttribute]
    public void SomeTransactedMethod()
    { /*do stuff */ }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红ご颜醉 2024-11-22 19:54:10

假设您正在使用 Ninject.Extensions.Interception 这应该可以解决问题

public class TransactionInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Do something...
    }
}

public class TransactionAttribute : InterceptAttribute
{
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return new TransactionInterceptor();
    }
}

public class SomeClass
{
    [Transaction]
    public virtual void SomeTransactedMethod() { }
}

确保应该拦截的方法是标记为虚拟。

当调用 SomeTransactedMethod() 时,它应该被拦截。

var kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf();

var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();

更新

您可以创建自定义规划策略。

public class CustomPlanningStrategy<TAttribute, TInterceptor> :
    NinjectComponent, IPlanningStrategy
        where TAttribute : Attribute
        where TInterceptor : IInterceptor
{
    private readonly IAdviceFactory adviceFactory;
    private readonly IAdviceRegistry adviceRegistry;

    public CustomPlanningStrategy(
        IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry)
        {
            this.adviceFactory = adviceFactory;
            this.adviceRegistry = adviceRegistry;
        }

        public void Execute(IPlan plan)
        {
            var methods = GetCandidateMethods(plan.Type);
            foreach (var method in methods)
            {
                var attributes = method.GetCustomAttributes(
                    typeof(TAttribute), true) as TAttribute[];
                if (attributes.Length == 0)
                {
                    continue;
                }

                var advice = adviceFactory.Create(method);

                advice.Callback = request => request.Kernel.Get<TInterceptor>();
                adviceRegistry.Register(advice);

                if (!plan.Has<ProxyDirective>())
                {
                    plan.Add(new ProxyDirective());
                }
            }
        }
    }

    private static IEnumerable<MethodInfo> GetCandidateMethods(Type type)
    {
        var methods = type.GetMethods(
            BindingFlags.Public | 
            BindingFlags.NonPublic | 
            BindingFlags.Instance
        );

        return methods.Where(ShouldIntercept);
    }

    private static bool ShouldIntercept(MethodInfo methodInfo)
    {
        return methodInfo.DeclaringType != typeof(object) &&
               !methodInfo.IsPrivate &&
               !methodInfo.IsFinal;
    }
}

现在应该可以了。

var kernel = new StandardKernel();
kernel.Components.Add<IPlanningStrategy, 
    CustomPlanningStrategy<TransactionAttribute, TransactionInterceptor>>();

kernel.Bind<SomeClass>().ToSelf();

var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();

Assuming that you are using Ninject.Extensions.Interception this should do the trick

public class TransactionInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Do something...
    }
}

public class TransactionAttribute : InterceptAttribute
{
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return new TransactionInterceptor();
    }
}

public class SomeClass
{
    [Transaction]
    public virtual void SomeTransactedMethod() { }
}

Make sure that the method that should be intercepted is marked as virtual.

When SomeTransactedMethod() is called it should be intercepted.

var kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf();

var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();

UPDATE

You could create a custom planning strategy.

public class CustomPlanningStrategy<TAttribute, TInterceptor> :
    NinjectComponent, IPlanningStrategy
        where TAttribute : Attribute
        where TInterceptor : IInterceptor
{
    private readonly IAdviceFactory adviceFactory;
    private readonly IAdviceRegistry adviceRegistry;

    public CustomPlanningStrategy(
        IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry)
        {
            this.adviceFactory = adviceFactory;
            this.adviceRegistry = adviceRegistry;
        }

        public void Execute(IPlan plan)
        {
            var methods = GetCandidateMethods(plan.Type);
            foreach (var method in methods)
            {
                var attributes = method.GetCustomAttributes(
                    typeof(TAttribute), true) as TAttribute[];
                if (attributes.Length == 0)
                {
                    continue;
                }

                var advice = adviceFactory.Create(method);

                advice.Callback = request => request.Kernel.Get<TInterceptor>();
                adviceRegistry.Register(advice);

                if (!plan.Has<ProxyDirective>())
                {
                    plan.Add(new ProxyDirective());
                }
            }
        }
    }

    private static IEnumerable<MethodInfo> GetCandidateMethods(Type type)
    {
        var methods = type.GetMethods(
            BindingFlags.Public | 
            BindingFlags.NonPublic | 
            BindingFlags.Instance
        );

        return methods.Where(ShouldIntercept);
    }

    private static bool ShouldIntercept(MethodInfo methodInfo)
    {
        return methodInfo.DeclaringType != typeof(object) &&
               !methodInfo.IsPrivate &&
               !methodInfo.IsFinal;
    }
}

This should now work.

var kernel = new StandardKernel();
kernel.Components.Add<IPlanningStrategy, 
    CustomPlanningStrategy<TransactionAttribute, TransactionInterceptor>>();

kernel.Bind<SomeClass>().ToSelf();

var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();
无妨# 2024-11-22 19:54:10

这是我用于相同目的的代码

//Code in Bind Module
this.Bind(typeof(ServiceBase<,>))
    .ToSelf()
    .InRequestScope()
    .Intercept()
    .With<TransactionInterceptor>();

以及

public class TransactionInterceptor : IInterceptor
{
    #region Constants and Fields

    public ISession session;
    private ISessionFactory sessionFactory;

    #endregion

    #region Constructors and Destructors

    public TransactionInterceptor(ISession session, ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
        this.session = session;
    }


    #endregion

    public void Intercept(IInvocation invocation)
    {
        try
        {
            if (!session.IsConnected)
                session = sessionFactory.OpenSession();

            session.BeginTransaction();
            invocation.Proceed();
            if (this.session == null)
            {
                return;
            }

            if (!this.session.Transaction.IsActive)
            {
                return;
            }
            else
            {
                this.session.Transaction.Commit();
            }
        }
        catch (Exception)
        {
            if (this.session == null)
            {
                return;
            }

            if (!this.session.Transaction.IsActive)
            {
                return;
            }

            this.session.Transaction.Rollback();

            throw;
        }
    }
}

TransactionAttribute 的代码

public class TransactionAttribute : InterceptAttribute
{
    #region Public Methods

    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return request.Context.Kernel.Get<TransactionInterceptor>() ;
    }

    #endregion
}

Here is the code that I used for the same purpose

//Code in Bind Module
this.Bind(typeof(ServiceBase<,>))
    .ToSelf()
    .InRequestScope()
    .Intercept()
    .With<TransactionInterceptor>();

And

public class TransactionInterceptor : IInterceptor
{
    #region Constants and Fields

    public ISession session;
    private ISessionFactory sessionFactory;

    #endregion

    #region Constructors and Destructors

    public TransactionInterceptor(ISession session, ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
        this.session = session;
    }


    #endregion

    public void Intercept(IInvocation invocation)
    {
        try
        {
            if (!session.IsConnected)
                session = sessionFactory.OpenSession();

            session.BeginTransaction();
            invocation.Proceed();
            if (this.session == null)
            {
                return;
            }

            if (!this.session.Transaction.IsActive)
            {
                return;
            }
            else
            {
                this.session.Transaction.Commit();
            }
        }
        catch (Exception)
        {
            if (this.session == null)
            {
                return;
            }

            if (!this.session.Transaction.IsActive)
            {
                return;
            }

            this.session.Transaction.Rollback();

            throw;
        }
    }
}

And code for TransactionAttribute

public class TransactionAttribute : InterceptAttribute
{
    #region Public Methods

    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return request.Context.Kernel.Get<TransactionInterceptor>() ;
    }

    #endregion
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文