C#中增强类功能的几种方式详解

2020-01-05 10:14:17刘景俊

动态代理


namespace DynamicProxy
{
 using Microsoft.Extensions.DependencyInjection;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
 using System.Reflection;

 /// <summary>
 /// 方法拦截器接口
 /// </summary>
 public interface IMethodInterceptor
 {
  /// <summary>
  /// 调用拦截器
  /// </summary>
  /// <param name="targetMethod">拦截的目标方法</param>
  /// <param name="args">拦截的目标方法参数列表</param>
  /// <returns>拦截的目标方法返回值</returns>
  object Interceptor(MethodInfo targetMethod, object[] args);
 }

 /// <summary>
 /// 代理类生成器
 /// </summary>
 public class ProxyFactory : DispatchProxy
 {
  private IMethodInterceptor _interceptor;

  /// <summary>
  /// 创建代理类实例
  /// </summary>
  /// <param name="targetType">要代理的接口</param>
  /// <param name="interceptor">拦截器</param>
  /// <returns></returns>
  public static object CreateInstance(Type targetType, IMethodInterceptor interceptor)
  {
   object proxy = GetProxy(targetType);
   ((ProxyFactory)proxy).GetInterceptor(interceptor);
   return proxy;
  }

  /// <summary>
  /// 创建代理类实例
  /// </summary>
  /// <param name="targetType">要代理的接口</param>
  /// <param name="interceptorType">拦截器</param>
  /// <param name="parameters">拦截器构造函数参数值</param>
  /// <returns>代理实例</returns>
  public static object CreateInstance(Type targetType, Type interceptorType, params object[] parameters)
  {
   object proxy = GetProxy(targetType);
   ((ProxyFactory)proxy).GetInterceptor(interceptorType, parameters);
   return proxy;
  }


  /// <summary>
  /// 创建代理类实例
  /// </summary>
  /// <typeparam name="TTarget">要代理的接口</typeparam>
  /// <typeparam name="TInterceptor">拦截器</typeparam>
  /// <param name="parameters">拦截器构造函数参数值</param>
  /// <returns></returns>
  public static TTarget CreateInstance<TTarget, TInterceptor>(params object[] parameters) where TInterceptor : IMethodInterceptor
  {
   object proxy = GetProxy(typeof(TTarget));
   ((ProxyFactory)proxy).GetInterceptor(typeof(TInterceptor), parameters);
   return (TTarget)proxy;
  }

  /// <summary>
  /// 获取代理类
  /// </summary>
  /// <param name="targetType"></param>
  /// <returns></returns>
  private static object GetProxy(Type targetType)
  {
   MethodCallExpression callexp = Expression.Call(typeof(DispatchProxy), nameof(DispatchProxy.Create), new[] { targetType, typeof(ProxyFactory) });
   return Expression.Lambda<Func<object>>(callexp).Compile()();
  }

  /// <summary>
  /// 获取拦截器
  /// </summary>
  /// <param name="interceptorType"></param>
  /// <param name="parameters"></param>
  private void GetInterceptor(Type interceptorType, object[] parameters)
  {
   Type[] ctorParams = parameters.Select(x => x.GetType()).ToArray();
   IEnumerable<ConstantExpression> paramsExp = parameters.Select(x => Expression.Constant(x));
   NewExpression newExp = Expression.New(interceptorType.GetConstructor(ctorParams), paramsExp);
   this._interceptor = Expression.Lambda<Func<IMethodInterceptor>>(newExp).Compile()();
  }

  /// <summary>
  /// 获取拦截器
  /// </summary>
  /// <param name="interceptor"></param>
  private void GetInterceptor(IMethodInterceptor interceptor)
  {
   this._interceptor = interceptor;
  }

  /// <summary>
  /// 执行代理方法
  /// </summary>
  /// <param name="targetMethod"></param>
  /// <param name="args"></param>
  /// <returns></returns>
  protected override object Invoke(MethodInfo targetMethod, object[] args)
  {
   return this._interceptor.Interceptor(targetMethod, args);
  }
 }

 /// <summary>
 /// 表演者
 /// </summary>
 public interface IPerform
 {
  /// <summary>
  /// 唱歌
  /// </summary>
  void Sing();

  /// <summary>
  /// 跳舞
  /// </summary>
  void Dance();
 }

 /// <summary>
 /// 具体的表演者——刘德华 Andy
 /// </summary>
 public class AndyPerformer : IPerform
 {
  public void Dance()
  {
   System.Console.WriteLine("给大家表演一个舞蹈");
  }

  public void Sing()
  {
   System.Console.WriteLine("给大家唱首歌");
  }
 }

 /// <summary>
 /// 经纪人——负责演员的所有活动
 /// </summary>
 public class PerformAgent : IMethodInterceptor
 {
  public IPerform _perform;
  public PerformAgent(IPerform perform)
  {
   this._perform = perform;
  }
  public object Interceptor(MethodInfo targetMethod, object[] args)
  {
   System.Console.WriteLine("各位大佬,要我们家艺人演出清闲联系我");
   object result = targetMethod.Invoke(this._perform, args);
   System.Console.WriteLine("各位大佬,表演结束该付钱了");
   return result;
  }
 }

 public class Program
 {
  static void Main(string[] args)
  {
   IPerform perform;

   //perform = ProxyFactory.CreateInstance<IPerform, PerformAgent>(new AndyPerformer());
   //perform.Sing();
   //perform.Dance();

   ServiceCollection serviceDescriptors = new ServiceCollection();
   serviceDescriptors.AddSingleton<IPerform>(ProxyFactory.CreateInstance<IPerform, PerformAgent>(new AndyPerformer()));
   IServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();
   perform = serviceProvider.GetService<IPerform>();
   perform.Sing();
   perform.Dance();

   System.Console.ReadKey();
  }
 }

}