动态代理模式
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); } }
运行结果: