Castle Windsor 的AOP 实践

前言:

最近接手了一个二手项目,该项目的最大特点就是 拥有众多的上下游 外部产品或项目。运维时总会时不时出现各种异常(有系统本身的,有业务的),这时要求能最快定位到问题点。这就需要有详细的日志流来支撑这样的工作。

翻开代码查看,记录日志的模式主要靠埋点(如:访问某某ESB服务花了多少时间,返回值是多少)。做为一个老司机,非常痛恨这种埋点,因为没有做到日志与业务解耦。而且违背功能单一原则。

解决思路

当然想到了AOP,让我们的业务代码跟我们的运维代码 和一些非业务流程代码实现解耦。

这时候想到了 Castle Windsor,Castle Windsor 提供了IOC容器实践,同时支持AOP思想。

实践

Nuget 安装 Castle.Core 和 Castle.Windsor

Castle Windsor 的AOP 实践_第1张图片

 

1、定义我们的业务抽象接口(契约)

public interface IMessageService

{

IEnumerable GetTasks(Guid userId,int pageIndex,int pageSize,out int rowCount);

}

2、定义业务实现类

public IEnumerable GetTasks(Guid userId, int pageIndex, int pageSize, out int rowCount)
        {
            rowCount = 20;

            List messages = new List();
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now , Id = Guid.NewGuid() , Title = "001" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "002" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "003" });

            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "004" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "005" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "006" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "007" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "008" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "009" });
            messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "010" });
            return messages;
        }

3、编写日志记录器

 public class LogInterceptor : IInterceptor //必须实现这个接口
    {
        public void Intercept(IInvocation invocation)
        {
            var methodName = invocation.Method.Name;
            try
            {
                Console.WriteLine(string.Format("Entered Method:{0}, Arguments: {1}", methodName, string.Join(",", invocation.Arguments)));
                invocation.Proceed(); //这里是业务类的方法
                Console.WriteLine(string.Format("Sucessfully executed method:{0}", methodName));
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Format("Method:{0}, Exception:{1}", methodName, e.Message));
                throw;
            }
            finally
            {
                Console.WriteLine(string.Format("Exiting Method:{0}", methodName));
            }
        }
    }

4、编写注册类(注册我们的业务抽象的实现,以及绑定具体的插片(如:日志))

public class ComponentRegistration : IRegistration
    {
        public void Register(IKernelInternal kernel)
        {
            kernel.Register(
                Component.For().ImplementedBy());

            kernel.Register(Component.For().ImplementedBy().Interceptors(InterceptorReference.ForType()).Anywhere);
        }
    }

5、初始化我们的依赖,在项目启动时调用

DependencyResolver.Initialize();

 

public class DependencyResolver
    {
        private static IWindsorContainer _container;

        //Initialize the container
        public static void Initialize()
        {
            _container = new WindsorContainer();
            _container.Register(new ComponentRegistration());
        }

        //Resolve types
        public static T For()
        {
            return _container.Resolve();
        }
    }

总结

当然ComponentRegistration 里的内容非常推荐搞到配置文件里。毕竟在代码里写死是一件非常糟糕的事情。

Castle.Windsor 还有非常丰富的注入方式,可以上网搜。这里只是说明对IOC和AOP的支持。

你可能感兴趣的:(C#技术文档)