动态代理模式


Dynamic Proxy

情景:

定义银行接口,包含两个方法 存钱和取钱

需要在原有接口基础上记录存钱和取钱的次数相关信息;

Nuget:ImpromptuInterface

 实现:

    public interface IBankAccount 
    {
        void Deposit(int amount);
        bool WithDraw(int amount);
        string ToString();

    } 
    public class BankAccount : IBankAccount
    {
        private int balance;
        private int overdraftLimit=-500;
        public void Deposit(int amount)
        {
            balance += amount;
            Console.WriteLine($"Deposit{amount} balance is now {balance}");
        }

        public bool WithDraw(int amount)
        {
            if (balance- amount >= overdraftLimit)
            {
                balance -= amount;
                Console.WriteLine($"WithDraw{amount} balance is now {balance}");
                return true;
            }
            return false; 
        }

        public override string ToString()
        {
            return $"{ nameof(balance)}: {balance}"; 
        }
    }
   

    public  class Log:DynamicObject
        where T:class,new()
    {
        private T subject;
        private Dictionary<string, int> methodCallCount = new();
        public Log(T subject)
        {
            this.subject = subject;
        }
        public static  I As() where I:class
        {
            if (!typeof(I).IsInterface)
                throw new ArgumentException("Must be an Interface");
            return new Log(new T()).ActLike();
        }
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            try
            {
                Console.WriteLine($"Invoking {subject.GetType().Name}.{binder.Name} with arguments [{string.Join(',', args)}]");
                if (methodCallCount.ContainsKey(binder.Name))
                    methodCallCount[binder.Name]++;
                else methodCallCount[binder.Name] = 1;

                result = subject.GetType().GetMethod(binder.Name).Invoke(subject, args);
                return true;

            }
            catch 
            {
                result = null;
                return false; 
            }

           // return base.TryInvokeMember(binder, args, out result);
        }
        public string Info 
        { 
            get 
            {
                StringBuilder sb = new StringBuilder();
                foreach (var item in methodCallCount)
                {
                    sb.AppendLine($"{item.Key} Excute {item.Value} time(s)");
                }
                return sb.ToString();
            }
        }
        public override string ToString()
        {
            return $"{Info} \n{subject}";
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            var ba = Log.As();
            ba.Deposit(500);
            ba.WithDraw(200);
            Console.WriteLine(ba);
        }
    }

运行结果: