使用.Net代理模式做类的增强

简介: 我们已经实现了用户注册功能,现在想增加日志记录功能。具体来讲就是在用户注册前后,分别输出一条日志。

我们已经实现了用户注册功能,现在想增加日志记录功能。具体来讲就是在用户注册前后,分别输出一条日志。我们当然可以修改原有的业务代码。

现在换个角度来问两个问题:
1. 团队开发中,我们很可能根本拿不到源代码,那又怎么去增加这个功能呢?
2. 这次需求是增加日志,以后再增加其他需求(比如异常处理),是不是仍然要改业务类呢?

总结一下:
我们要在不修改原有类业务代码的前提下,去做类的增强。我们的设计要符合面向对象的原则:对扩展开放,对修改封闭

都有哪些办法呢?我们尝试以下几种方法:


原有业务类

业务模型

namespace testAopByDecorator
{
    public class User
    {
        public string Name { get; set; }
        public int Id { get; set; }
    }
}

接口设计

namespace testAopByDecorator
{
    public interface IUserProcessor
    {
        void RegisterUser(User user);
    }
}

业务实现

using System;

namespace testAopByDecorator
{
    public class UserProcessor : IUserProcessor
    {
        public void RegisterUser(User user)
        {
            if (user == null)
            {
                return;
            }

            Console.WriteLine(string.Format("注册了一个用户{0}:{1}", user.Id, user.Name));
        }
    }
}

上层调用

using System;

namespace testAopByDecorator
{
    class Program
    {
        private static User user = new User { Id = 1, Name = "滇红" };

        static void Main(string[] args)
        {
            Register();
            Console.ReadKey();
        }

        private static void Register()
        {
            IUserProcessor processor = new UserProcessor();
            processor.RegisterUser(user);
        }
    }
}

使用.Net代理模式做类的增强

我们将使用.net提供的System.Runtime.Remoting.Proxies.RealProxy来对原有的类做业务增强。

using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

namespace testAopByProxy
{
    public class UserProcessorProxy : RealProxy
    {
        private IUserProcessor _processor;

        public UserProcessorProxy(IUserProcessor processor): base(typeof(IUserProcessor))
        {
            this._processor = processor;
        }

        public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage callMessage = (IMethodCallMessage)msg;
            User user = callMessage.Args[0] as User;

            before(user);
            object returnValue = (IMethodReturnMessage)callMessage.MethodBase.Invoke(this._processor, callMessage.Args);
            after(user);

            return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
        }

        private void after(User user)
        {
            Console.WriteLine("注册用户后:" + user.Name);
        }

        private void before(User user)
        {
            Console.WriteLine("注册用户前:" + user.Name);
        }
    }
}

上层调用

using System;

namespace testAopByProxy
{
    class Program
    {
        private static User user = new User { Id = 1, Name = "滇红" };

        static void Main(string[] args)
        {
            RegisterAndLog();
            Console.ReadKey();
        }

        private static void RegisterAndLog()
        {
            IUserProcessor processor = new UserProcessor();
            IUserProcessor proxy = (IUserProcessor)new UserProcessorProxy(processor).GetTransparentProxy();//代理原有业务类
            proxy.RegisterUser(user);//遵守接口契约
        }
    }
}

对比一下扩展前后的业务展现
这里写图片描述

相关文章
|
IDE API 开发工具
拦截|篡改|伪造.NET类库中不限于public的类和方法
本文除了回顾拦截.NET类库中的方法,实现方法参数的篡改、方法返回结果的伪造,再着重介绍.NET类库中非public类及方法如何拦截。
拦截|篡改|伪造.NET类库中不限于public的类和方法
|
1月前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
12天前
.NET 4.0下实现.NET4.5的Task类相似功能组件
【10月更文挑战第29天】在.NET 4.0 环境下,可以使用 `BackgroundWorker` 类来实现类似于 .NET 4.5 中 `Task` 类的功能。`BackgroundWorker` 允许在后台执行耗时操作,同时不会阻塞用户界面线程,并支持进度报告和取消操作。尽管它有一些局限性,如复杂的事件处理模型和不灵活的任务管理方式,但在某些情况下仍能有效替代 `Task` 类。
|
1月前
|
API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
21 0
|
3月前
|
缓存 程序员
封装一个给 .NET Framework 用的内存缓存帮助类
封装一个给 .NET Framework 用的内存缓存帮助类
|
5月前
|
存储 Go C#
【.NET Core】深入理解IO之File类
【.NET Core】深入理解IO之File类
75 6
|
5月前
|
存储 开发框架 缓存
【.NET Core】你真的了解HttpRuntime类吗
【.NET Core】你真的了解HttpRuntime类吗
46 0
|
6月前
|
消息中间件
.NET 中 Channel 类简单使用
`System.Threading.Channels` 提供异步生产者-消费者数据结构,用于.NET Standard上的跨平台同步。频道实现生产者/消费者模型,允许在任务间异步传递数据。简单示例展示如何创建无界和有界频道,以及多生产者和消费者共享频道的场景。频道常用于内存中的消息队列,通过控制生产者和消费者的速率来调整系统流量。
|
6月前
|
SQL 数据库连接 数据库
VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤
VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤
287 0
|
开发框架 前端开发 .NET
ASP.NET Core 基础知识之​Startup 类配置
Startup 类配置服务和应用的请求管道。
151 0