AOP拦截属性

发布于 2024-08-12 13:56:36 字数 1590 浏览 9 评论 0原文

所以,我遇到了这个问题,似乎没有人能够提供帮助。因此,我不会继续抨击它,而是将其扔到那里寻找其他方法来剥这只特殊的猫的皮。

我目前有以下内容:

public interface ICustomerService
{
    Customer GetCustomer(int id);
}

public class CustomerService : ICustomerService
{
    public Customer GetCustomer(int id)
    {
        ...
    }
}

...并且使用Unity我有IOC设置,同时配置拦截,例如:

IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<ICustomerService, CustomerService>()
    .Configure<Interception>()
    .SetInterceptorFor<ICustomerService>(new InterfaceInterceptor());

我想要实现的是能够像这样在界面中放置属性:

public interface ICustomerService
{
    [Log]
    Customer GetCustomer(int id);
}

...定义如下:

public class LogAttribute: HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogHandler();
    }
}  

...然后在 LogHandler 类中执行我想要的所有日志记录,例如:

public class LogHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        ... log stuff
    }
}

我想要实现的是一个跟踪/日志记录系统,其中处理程序记录正在调用的名称空间.class.methodname 以及父名称空间.class。调用该方法的方法名。我尝试使用“输入”IMethodInitation 参数来获取我想要的信息,但没有成功,问题是,输入返回“ICustomerService”接口,同时检查父级的堆栈帧返回父级的实现类(例如.CustomerService)意味着当我尝试使用namespace.class.methodname作为实体ID创建树结构时,ID和parentID不匹配。

将参数放入 [Log] 属性中也不会真正起作用,因为我可以在那里放入什么?如果我输入接口名称,我仍然遇到与上面相同的问题,其中一个的 ID 是一个接口,而父级是实现类。而且,我无法将实现类名称放在接口的属性中,因为这首先违背了拥有接口的目的!

所以,这就是困境。有人有新想法吗?

So, i have this problem, and no one seems to be able to help. So rather than keep bashing away i'm going to throw it out there for alternative ways to skin this particular cat.

I currently have the following:

public interface ICustomerService
{
    Customer GetCustomer(int id);
}

public class CustomerService : ICustomerService
{
    public Customer GetCustomer(int id)
    {
        ...
    }
}

... and with Unity i have IOC setup, and at the same time configuring interception like :

IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<ICustomerService, CustomerService>()
    .Configure<Interception>()
    .SetInterceptorFor<ICustomerService>(new InterfaceInterceptor());

What i want to achive is to be able to place attributes in the interface like this:

public interface ICustomerService
{
    [Log]
    Customer GetCustomer(int id);
}

... defined like :

public class LogAttribute: HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogHandler();
    }
}  

... and then in the LogHandler class do all the logging that i want like :

public class LogHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        ... log stuff
    }
}

What i want to achieve is a tracing/logging system where the handler logs what namespace.class.methodname is being called, AND the parent namespace.class.methodname that called that. I've tried with no success to use the "input" IMethodInvocation parameter to get the info i want, the issue being, input returns the "ICustomerService" interface, whilst checking a stackframe for the parent returns the implemented class of the parent (eg. CustomerService) meaning that when i try to create a tree structure using the namespace.class.methodname as the entitys ID's, the ID's and parentID's don't match up.

Dropping a parameter into the [Log] attribute isn't going to work either really, because what could i put in there? If i put the interface name, i still have the same problem as above where the ID of one is an interface and the parent is the implementing class. And, i can't put the implementing class name in the attribute on the interface as that defeats the purpose of having an interface in the first place!

So, that's the dilema. Anyone got fresh ideas?

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

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

发布评论

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

评论(2

別甾虛僞 2024-08-19 13:56:37

我最终使用 PostSharp 来实现与此完全相同的日志记录。 http://www.postsharp.org

I ended up using PostSharp to implement logging exactly like this. http://www.postsharp.org

碍人泪离人颜 2024-08-19 13:56:37

我已经使用 Unity 和 Interception 进行日志记录。由于我严重缺乏配置设置技能,我不得不以编程方式完成此操作。您需要设置至少一个拦截器,以及一个或多个策略对象。哦,是的,UnityContainer.Configure 至关重要。

有点像这样:

// I'm using the TransparentProxyInterceptor because I want to trace EVERYTHING...
var intp = myUnityContainer.Configure<Interception>().
    SetInterceptorFor(typeof(MyTypeToLog), new TransparentProxyInterceptor());

var policy = intp.AddPolicy("somePolicyName");

policy.AddMatchingRule<TypeMatchingRule>(
    new InjectionConstructor(
        new InjectionParameter(typeof(MyTypeToLog)))
          .AddCallHandler(typeof(MyCallHandler), 
               new ContainerControlledLifetimeManager());

当然我还需要定义拦截调用处理程序:

public class MyCallHandler : ICallHandler, IDisposable
{
    public IMethodReturn Invoke(IMethodInvocation input, 
        GetNextHandlerDelegate getNext)
    {
        var methodReturn = getNext().Invoke(input, getNext);

        // log everything...
        LogMethodCall(input, methodReturn);

        // log exception if there is one...
        if (methodReturn.Exception != null)
        {
            LogException(methodReturn);
        }

        return methodReturn;
    }
}

I've got logging working using Unity and Interception. Due to my horrendous lack of configuration setup skills, I had to do it programmatically. You need to set up at least one interceptor, as well as one or more policy objects. Oh yeah, the UnityContainer.Configure<Interception> is critical.

Kind of like this:

// I'm using the TransparentProxyInterceptor because I want to trace EVERYTHING...
var intp = myUnityContainer.Configure<Interception>().
    SetInterceptorFor(typeof(MyTypeToLog), new TransparentProxyInterceptor());

var policy = intp.AddPolicy("somePolicyName");

policy.AddMatchingRule<TypeMatchingRule>(
    new InjectionConstructor(
        new InjectionParameter(typeof(MyTypeToLog)))
          .AddCallHandler(typeof(MyCallHandler), 
               new ContainerControlledLifetimeManager());

Of course I need to define the interception call handler as well:

public class MyCallHandler : ICallHandler, IDisposable
{
    public IMethodReturn Invoke(IMethodInvocation input, 
        GetNextHandlerDelegate getNext)
    {
        var methodReturn = getNext().Invoke(input, getNext);

        // log everything...
        LogMethodCall(input, methodReturn);

        // log exception if there is one...
        if (methodReturn.Exception != null)
        {
            LogException(methodReturn);
        }

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