没有 IOC 的 AOP 建议 [英] AOP suggestion without IOC

查看:22
本文介绍了没有 IOC 的 AOP 建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在现有的 WCF 服务中引入 AOP,主要用于异常包装和日志记录.我需要 .NET 4(不是 4.5)中的 AOP 框架,不需要进行 IOC 注入,因为在现有代码中引入成本太高.在我的研究中,我发现了以下内容:

  • PostSharp:非常好且简单,但需要付费,我需要一个免费的
  • NConcern:最新版本是为 .NET 4.5 构建的,以前的版本在我的代码中存在问题.它也适用于修改程序集的 CNetpune,这不是我想要的.
  • Spring.NET:没有找到使用 IOC 进行 AOP 的方法
  • 其他人太老了,不再维护.

有什么建议吗?

解决方案

您可以使用 WCF 拦截器来实现您的 AOP,如下所示:

首先创建您的 BaseServiceInspector.实现 IDispatchMessageInspectorIParameterInspector

使用方法 AfterReceiveRequest 来初始化您的请求属性,BeforeCall 在服务调用之前记录,AfterCall 以记录服务被调用.>

我的实现是这样的:

////<摘要>///这个类负责检查服务请求和响应///服务操作也记录在这个类中///</总结>内部类 BaseServiceInspector : IClientMessageInspector, IDispatchMessageInspector, IParameterInspector{私人向导请求标识符;私人日期时间请求日期;私有字符串 serviceResult = String.Empty;私人字符串消费者IPAddress = String.Empty;私有字符串 operationName = String.Empty;公共对象 AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext){尝试{requestIdentifier = Guid.NewGuid();requestDate = DateTime.Now;operationName = ServiceHelper.GetServiceOperationName(OperationContext.Current);consumerIPAddress = ServiceHelper.GetServiceConsumerIPAddress(OperationContext.Current);返回空;}抓住{扔;}}公共对象 BeforeCall(字符串操作名称,对象 [] 输入){尝试{ServiceHelper.LogServiceIsCalled(operationName, requestIdentifier, consumerIPAddress, JsonConvert.SerializeObject(inputs, Formatting.Indented));}抓住{//不要中断日志异常的流程}返回空;}public void BeforeSendReply(ref 消息回复,对象相关状态){TimeSpan executeDuration = DateTime.Now - requestDate;ServiceHelper.LogServiceIsExecuted(operationName, executeDuration.Milliseconds,requestIdentifier, consumerIPAddress, serviceResult);}公共对象 BeforeSendRequest(ref Message request, IClientChannel channel){返回空;}}

然后创建您的方面

////<摘要>///为服务类型定制服务行为.如果服务被设计为 WCF 服务///所有服务都应该有这个属性///</总结>公共类 BaseServiceBehavior :属性,IServiceBehavior{public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){BaseServiceInspector baseServiceInspector = new BaseServiceInspector();foreach(serviceHostBase.ChannelDispatchers 中的ChannelDispatcher channelDispatcher){foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints){endpointDispatcher.DispatchRuntime.MessageInspectors.Add(baseServiceInspector);foreach(endpointDispatcher.DispatchRuntime.Operations 中的 var 操作){operation.ParameterInspectors.Add(baseServiceInspector);}}}}}

最后将您的方面添加到服务:

[BaseServiceBehavior]公共类 MathService : IMathService{//...}

希望它对你有用.

更多拦截器信息

您也可以查看我的 github 仓库以了解详细实现:

服务框架/

I need to introduce AOP in an existing WCF service, basically for exception wrapping and logging. I need an AOP framework in .NET 4 (not 4.5), without need to do IOC injection because it will be too costly to introduce in existing code. In my research I found the following:

  • PostSharp: very nice and straightforward but paid, I need a free one
  • NConcern: latest version is build for .NET 4.5, previous versions is buggy with my code. Also it works with CNetpune which modify the assembly, not exactly what I want.
  • Spring.NET: didn't find a way to do AOP with IOC
  • others are too old and not maintained any more.

any suggestion ?

解决方案

You can implement your AOP with using WCF Interceptors like this:

First create your BaseServiceInspector. Implement IDispatchMessageInspector and IParameterInspector

Use methods AfterReceiveRequest to initialize you request properties, BeforeCall to log before service is calling and AfterCall to log Service is Called.

My implementation like this:

/// <summary>
/// This class responsible to inspect service request and response
/// Service operations is also logged within this class
/// </summary>
internal class BaseServiceInspector : IClientMessageInspector, IDispatchMessageInspector, IParameterInspector
{
    private Guid requestIdentifier;
    private DateTime requestDate;
    private string serviceResult = String.Empty;
    private string consumerIPAddress = String.Empty;
    private string operationName = String.Empty;


    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        try
        {
            requestIdentifier = Guid.NewGuid();
            requestDate = DateTime.Now;
            operationName = ServiceHelper.GetServiceOperationName(OperationContext.Current);
            consumerIPAddress = ServiceHelper.GetServiceConsumerIPAddress(OperationContext.Current);

            return null;
        }
        catch
        {
            throw;
        }
    }

    public object BeforeCall(string operationName, object[] inputs)
    {
        try
        {
            ServiceHelper.LogServiceIsCalled(operationName, requestIdentifier, consumerIPAddress, JsonConvert.SerializeObject(inputs, Formatting.Indented));
        }
        catch
        {
            //Dont break the flow for log exception
        }

        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        TimeSpan executeDuration = DateTime.Now - requestDate;
        ServiceHelper.LogServiceIsExecuted(operationName, executeDuration.Milliseconds,requestIdentifier, consumerIPAddress, serviceResult);
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        return null;

    }
}

Then create your Aspect

/// <summary>
/// Customized service behavior for service types. If services are designed as WCF service
/// All services should have this attribute
/// </summary>
public class BaseServiceBehavior : Attribute, IServiceBehavior
{

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        BaseServiceInspector baseServiceInspector = new BaseServiceInspector();
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(baseServiceInspector);

                foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)
                {
                    operation.ParameterInspectors.Add(baseServiceInspector);
                }
            }
        }
    }
}

Finally add your Aspect to Service:

[BaseServiceBehavior]
public class MathService : IMathService
{
    //...
}

Hope it works for you.

More info for Interceptors

You can check my github repo as well for detail implementation:

Service-Framework/

这篇关于没有 IOC 的 AOP 建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆