你的位置:首页 > ASP.net教程

[ASP.net教程]基于Mono.Cecil的静态注入


Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了

 

动态注入有几种方式:

  1. 利用Remoting的ContextBoundObject或MarshalByRefObject。
  2. 动态代理(反射),很多AOP框架都用这种方式。
  3. MVC的filter,也是反射。

这里主要介绍静态注入

==========================================================================================

起初的想法是实现一种功能,自动给对象的属性一个默认值,想来想去没有什么好的解决方法,参考资料后决定使用Mono.Cecil修改生成的程序集来实现!

 

先定义一个接口

using System;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using System.Text;using System.Threading.Tasks;namespace System.Linq{  /// <summary>  /// 支持注入  /// </summary>  /// <typeparam name="T"></typeparam>  internal interface IInject<T>  {    /// <summary>    /// 注入属性    /// </summary>    /// <typeparam name="TKey"></typeparam>    /// <param name="name"></param>    /// <param name="value"></param>    /// <returns></returns>    IInject<T> InjectProperty<TKey>(Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type);  }}

 

定义一个描述类:

  internal class InjectItem  {    public string Name { get; set; }    /// <summary>    /// 表示生成的字段    /// </summary>    public FieldDefinition Field { get; set; }    /// <summary>    /// 标识生成字段成功    /// </summary>    public FieldDefinition SetOKField { get; set; }    /// <summary>    /// 标识    /// </summary>    public FieldDefinition ValueField { get; set; }    public Type FieldType { get; set; }    public Type Type { get; set; }    public Delegate Value { get; set; }    public MethodReference Method { get; set; }  }

 

 

定义一个缓存帮助类,存放程序集的一些数据:

 

using Mono.Cecil;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace System{  internal class CacheHelper  {    internal static readonly ICache<string, TupleCache<AssemblyDefinition, bool>> _assembly = CacheFactory.CreateCache<string, TupleCache<AssemblyDefinition, bool>>();    internal static readonly List<InjectItem> _setValue = new List<InjectItem>();    /// <summary>    /// 得到唯一程序集    /// </summary>    /// <param name="type"></param>    /// <returns></returns>    internal static TupleCache<AssemblyDefinition, bool> GetAssembly(Type type)    {      var ass = type.Assembly;      var path = ass.CodeBase.TrimStart("file:///".ToCharArray());      return _assembly.Get(path, () =>      {        return new TupleCache<AssemblyDefinition, bool>(AssemblyDefinition.ReadAssembly(path), false);      });    }  }}

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace System{  internal class TupleCache<T1, T2>  {    public TupleCache(T1 item1, T2 item2)    {      Item1 = item1;      Item2 = item2;    }    public T1 Item1 { get; set; }    public T2 Item2 { get; set; }  }}

 

 

 

定义一个枚举,标识怎么处理映射:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace System.Linq{  /// <summary>  /// 指定注入类型  /// </summary>  //[Flags]  public enum InjectType  {    /// <summary>    /// 忽略原属性值    /// </summary>    IgnoreOldValue = 1,    /// <summary>    /// 检查原属性默认值    /// </summary>    CheckOldValueDefault = 2,    /// <summary>    /// 当属性值改变时重新赋值    /// </summary>    ReadOnValueChanged = 3,    /// <summary>    /// 当属性值改变时重新赋值(检查属性默认值)    /// </summary>    ReadOnValueChangedCheckOldValueDefault = 4  }}

 

 

接下来是具体实现:

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Reflection.Emit;using System.Linq.Expressions;using System.Reflection;using Mono.Cecil;using System.Collections;using System.Collections.ObjectModel;using Mono.Cecil.Cil;namespace System.Linq{  internal class InjectItem  {    public string Name { get; set; }    /// <summary>    /// 表示生成的字段    /// </summary>    public FieldDefinition Field { get; set; }    /// <summary>    /// 标识生成字段成功    /// </summary>    public FieldDefinition SetOKField { get; set; }    /// <summary>    /// 标识    /// </summary>    public FieldDefinition ValueField { get; set; }    /// <summary>    /// 字段类型    /// </summary>    public Type FieldType { get; set; }    /// <summary>    /// 属性类型    /// </summary>    public Type Type { get; set; }    public Delegate Value { get; set; }    public MethodReference Method { get; set; }  }  internal sealed class InjectBase<T> : IInject<T>  {    /// <summary>    /// 生成的字段名    /// </summary>    static readonly string _fieldName = "___Inject_Property_Name_{0}___";    static readonly string _setFieldName = "___Inject_Property_Name_{0}___OK";    static readonly string _methodName = "___Inject_Method_CheckDefaultValue___";    Collection<InjectItem> _injectItems = new Collection<InjectItem>();    internal InjectBase()    {      _type = typeof(T);      if (_type.IsNested)      {        throw new ArgumentException(_type.FullName + " is a private class!");      }      _assemby = CacheHelper.GetAssembly(_type);      _typeDefinition = GetTypeFromAssembly();      if (_typeDefinition == null)      {        throw new ArgumentException("type is undefined!");      }    }    /// <summary>    /// 要处理的类型    /// </summary>    Type _type;    /// <summary>    /// 当前类型所对应的Mono.Cecil描述程序集    /// </summary>    TupleCache<AssemblyDefinition, bool> _assemby;    /// <summary>    /// 当前类型对应的Mono.Cecil描述类型    /// </summary>    TypeDefinition _typeDefinition;    /// <summary>    /// 获取类型对应的Mono.Cecil描述类型    /// </summary>    /// <returns></returns>    TypeDefinition GetTypeFromAssembly()    {      foreach (var item in _assemby.Item1.Modules)      {        var type = item.Types.FirstOrDefault(o => o.FullName == _type.FullName);        if (type != null)        {          return type;        }      }      return null;    }    Tuple<InjectItem, bool> OnInject<TKey>(Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue)    {      //if (!typeof(MemberExpression).IsAssignableFrom(propertyName.Body.GetType()) && propertyName.Body.GetType().Name != "PropertyExpression")      if (propertyName.Body.GetType().Name != "PropertyExpression")      {        throw new ArgumentException("propertyName is not a property expression!");      }      var body = propertyName.Body as MemberExpression;      string name = body.Member.Name;      //指示是否处理过了当前类型      TypeDefinition newType = _assemby.Item1.MainModule.Types.FirstOrDefault(o => o.FullName == InjectMap._classType.Item1 + "." + InjectMap._classType.Item2);      //字段      string fieldName = string.Format(_fieldName, name);      if (newType != null)      {        //处理过类型的其他属性了        //看看是否处理了当前属性        var injectItem1 = _injectItems.FirstOrDefault(o => o.Name == fieldName);        if (injectItem1 == null)        {          //没处理          injectItem1 = new InjectItem()          {            Name = fieldName,            Type = _type          };          _injectItems.Add(injectItem1);          CacheHelper._setValue.Add(injectItem1);        }        return new Tuple<InjectItem, bool>(injectItem1, true);      }      _assemby.Item2 = true;      //得到属性      var property = _typeDefinition.Properties.FirstOrDefault(o => o.Name == name);      var getMethod = property.GetMethod;      var setMethod = property.SetMethod;      //如果不可读      if (getMethod == null)      {        throw new ArgumentException("property " + name + " on " + _type.FullName + " is writeonly!");      }      var injectItem = _injectItems.FirstOrDefault(o => o.Name == fieldName);      if (injectItem == null)      {        var field = _typeDefinition.Fields.FirstOrDefault(o => o.Name == fieldName);        FieldDefinition valueField = null;        FieldDefinition setFieldOK = null;        if (field == null)        {          //field = new FieldDefinition(fieldName, Mono.Cecil.FieldAttributes.Private | Mono.Cecil.FieldAttributes.Static, new TypeReference("System", typeof(Func<T, TKey>).Name, ModuleDefinition.ReadModule(Assembly.GetAssembly(typeof(Func<T, TKey>)).Location), new ModuleReference("mscorlib.dll")));          field = new FieldDefinition(fieldName, Mono.Cecil.FieldAttributes.Private | Mono.Cecil.FieldAttributes.Static, _typeDefinition.Module.Import(typeof(Func<T, TKey>)));          valueField = new FieldDefinition(fieldName + "Value", Mono.Cecil.FieldAttributes.Private, property.PropertyType);          setFieldOK = new FieldDefinition(string.Format(_setFieldName, name), Mono.Cecil.FieldAttributes.Private, _typeDefinition.Module.Import(typeof(bool)));          _typeDefinition.Fields.Add(field);          _typeDefinition.Fields.Add(valueField);          _typeDefinition.Fields.Add(setFieldOK);          injectItem = new InjectItem()          {            Field = field,            ValueField = valueField,            Name = fieldName,            Type = _type,            FieldType = body.Member.DeclaringType,            SetOKField = setFieldOK,            Method = new MethodReference(fieldName, _typeDefinition.Module.Import(property.PropertyType), _typeDefinition.Module.Import(_typeDefinition))          };          _injectItems.Add(injectItem);          CacheHelper._setValue.Add(injectItem);        }        //else        //{        //  valueField = _typeDefinition.Fields.FirstOrDefault(o => o.Name == fieldName + "Value");        //  setFieldOK = _typeDefinition.Fields.FirstOrDefault(o => o.Name == string.Format(_setFieldName, name));        //}      }      ////DefaultMethod      //var checkDefaultMethod = _typeDefinition.Methods.FirstOrDefault(o => o.Name == _methodName);      //if (checkDefaultMethod == null)      //{      //  checkDefaultMethod = new MethodDefinition(_methodName, Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.Private, _typeDefinition.Module.Import(typeof(bool)));      //}      return new Tuple<InjectItem, bool>(injectItem, false);    }    public IInject<T> InjectProperty<TKey>(Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type)    {      //预处理      var item = OnInject(propertyName, propertyValue);      //编译值      item.Item1.Value = propertyValue.Compile();      if (item.Item2)      {        //已处理,不再继续        return this;      }      var body = propertyName.Body as MemberExpression;      string name = body.Member.Name;      var fieldName = string.Format(_fieldName, name);      var fieldValueName = fieldName + "Value";      //得到属性      var property = _typeDefinition.Properties.FirstOrDefault(o => o.Name == name);      var getMethod = property.GetMethod;      getMethod.Body.Instructions.Clear();      getMethod.Body.Variables.Add(new VariableDefinition("flag", _typeDefinition.Module.Import(typeof(bool))));      getMethod.Body.Variables.Add(new VariableDefinition(fieldValueName, _typeDefinition.Module.Import(property.PropertyType)));      //处理Get属性      if (type == InjectType.CheckOldValueDefault || type == InjectType.ReadOnValueChangedCheckOldValueDefault)      {        InjectPropertyInternalGetCheckDefault(item.Item1, getMethod, propertyName, propertyValue, type);      }      else      {        InjectPropertyInternalGet(item.Item1, getMethod, propertyName, propertyValue, type);      }      var setMethod = property.SetMethod;      if (setMethod != null)      {        //处理Set属性        setMethod.Body.Instructions.Clear();        if (type == InjectType.CheckOldValueDefault || type == InjectType.ReadOnValueChangedCheckOldValueDefault)        {          InjectPropertyInternalSetCheckDefault(item.Item1, setMethod, propertyName, propertyValue, type);        }        else        {          InjectPropertyInternalSet(item.Item1, setMethod, propertyName, propertyValue, type);        }      }      return this;    }    IInject<T> InjectPropertyInternalGet<TKey>(InjectItem item, MethodDefinition method, Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type)    {      method.Body.InitLocals = true;      var iLProcessor = method.Body.GetILProcessor();      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Nop);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.SetOKField);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.Item1.ValueField);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldnull);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ceq);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stloc_0);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_0);      List<Instruction> trueInstruction = new List<Instruction>();      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Nop));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldsfld, item.Field));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      var invokeMethod = _typeDefinition.Module.Import(typeof(Func<T, TKey>).GetMethod("Invoke"));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Callvirt, invokeMethod));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldc_I4_1));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stfld, item.SetOKField));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Nop));      List<Instruction> falseInstruction = new List<Instruction>();      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldfld, item.ValueField));      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stloc_1));      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Brfalse_S, falseInstruction[0]);      foreach (var instruction in trueInstruction)      {        iLProcessor.Append(instruction);      }      foreach (var instruction in falseInstruction)      {        iLProcessor.Append(instruction);      }      Instruction endInstruction = Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldloc_1);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Br_S, endInstruction);      iLProcessor.Append(endInstruction);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ret);      return this;    }    IInject<T> InjectPropertyInternalGetCheckDefault<TKey>(InjectItem item, MethodDefinition method, Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type)    {      var body = propertyName.Body as MemberExpression;      //method.Body.Variables.Add(new VariableDefinition("flag2", _typeDefinition.Module.Import(typeof(bool))));      //if (item.ValueField.FieldType.IsValueType)      //{      //  method.Body.Variables.Add(new VariableDefinition("defaultValue", _typeDefinition.Module.Import(body.Member.ReflectedType)));      //}      method.Body.InitLocals = true;      var iLProcessor = method.Body.GetILProcessor();      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Nop);      List<Instruction> flag1 = new List<Instruction>();      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldfld, item.SetOKField));      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldc_I4_0));      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ceq));      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stloc_0));      flag1.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldloc_0));      //校验默认值      if (!item.ValueField.FieldType.IsValueType)      {        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_2);      }      else      {        var equalsMethod = _typeDefinition.Module.Import(typeof(object).GetMethod("Equals", BindingFlags.Static | BindingFlags.Public));        var getHashCodeMethod = _typeDefinition.Module.Import(body.Member.DeclaringType.GetMethod("GetHashCode"));        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Bne_Un_S, flag1[0]);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stloc_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Bne_Un_S, flag1[0]);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.SetOKField);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Bne_Un_S, flag1[0]);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_2);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.SetOKField);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_2);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, getHashCodeMethod);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ceq);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stloc_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, getHashCodeMethod);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.ValueField);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, getHashCodeMethod);        //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Call, equalsMethod);      }      foreach (var instruction in flag1)      {        iLProcessor.Append(instruction);      }      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldfld, item.SetOKField);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ceq);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stloc_0);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_0);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ceq);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stloc_0);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldloc_0);      List<Instruction> trueInstruction = new List<Instruction>();      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Nop));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldsfld, item.Field));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      var invokeMethod = _typeDefinition.Module.Import(typeof(Func<T, TKey>).GetMethod("Invoke"));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Callvirt, invokeMethod));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldc_I4_1));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stfld, item.SetOKField));      trueInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Nop));      List<Instruction> falseInstruction = new List<Instruction>();      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldarg_0));      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldfld, item.ValueField));      falseInstruction.Add(Instruction.Create(Mono.Cecil.Cil.OpCodes.Stloc_1));      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Brfalse_S, falseInstruction[0]);      foreach (var instruction in trueInstruction)      {        iLProcessor.Append(instruction);      }      foreach (var instruction in falseInstruction)      {        iLProcessor.Append(instruction);      }      Instruction endInstruction = Instruction.Create(Mono.Cecil.Cil.OpCodes.Ldloc_1);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Br_S, endInstruction);      iLProcessor.Append(endInstruction);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ret);      return this;    }    IInject<T> InjectPropertyInternalSet<TKey>(InjectItem item, MethodDefinition method, Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type)    {      var iLProcessor = method.Body.GetILProcessor();      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_1);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);      if (type == InjectType.IgnoreOldValue)      {        iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_1);      }      else if (type == InjectType.ReadOnValueChanged)      {        iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);      }      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.SetOKField);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ret);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField);      return this;    }    IInject<T> InjectPropertyInternalSetCheckDefault<TKey>(InjectItem item, MethodDefinition method, Expression<Func<T, TKey>> propertyName, Expression<Func<T, TKey>> propertyValue, InjectType type)    {      var iLProcessor = method.Body.GetILProcessor();      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_1);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);      if (type == InjectType.CheckOldValueDefault)      {        iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_1);      }      else if (type == InjectType.ReadOnValueChangedCheckOldValueDefault)      {        iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4_0);      }      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.SetOKField);      iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Ret);      //iLProcessor.Emit(Mono.Cecil.Cil.OpCodes.Stfld, item.ValueField);      return this;    }  }}

View Code

 

以上就是主要代码,接下来给个入口就好了

 

using Mono.Cecil;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Web;namespace System.Linq{  public abstract class InjectMap  {    /// <summary>    /// 命名空间和类名,标识程序集已处理    /// </summary>    internal static readonly Tuple<string, string> _classType = new Tuple<string, string>("System.Inject", "Inject_Assemby_Over");    static bool _isMap = false;    internal static readonly ICache<Type, InjectMap> _cache = CacheFactory.CreateCache<Type, InjectMap>();    /// <summary>    /// 创建映射    /// </summary>    /// <typeparam name="T"></typeparam>    /// <returns></returns>    public static InjectMap<T> CreateMap<T>()    {      var map = _cache.Get(typeof(T), () => InjectMap<T>.Create()) as InjectMap<T>;      return map;    }    /// <summary>    /// 结束注入    /// 注意:方法会自动检测是否需要注入数据    /// 如果成功注入数据,则会重启应用程序    /// 注入数据后不会再次注入了    /// </summary>    public static void End()    {      bool reload = false;      foreach (var item in CacheHelper._assembly)      {        if (item.Value.Item2)        {          reload = true;          item.Value.Item1.MainModule.Types.Add(new TypeDefinition(_classType.Item1, _classType.Item2, Mono.Cecil.TypeAttributes.Class | Mono.Cecil.TypeAttributes.Public, item.Value.Item1.MainModule.Import(typeof(object))));          item.Value.Item1.Write(item.Key);        }      }      if (reload)      {        //会重启程序        CacheHelper._assembly.Flush();        CacheHelper._setValue.Clear();        _isMap = true;        if (HttpContext.Current != null)        {          //HttpRuntime.UnloadAppDomain();          //HttpRuntime.UnloadAppDomain();          File.SetLastWriteTime(System.Web.Hosting.HostingEnvironment.MapPath("~/web.config"), DateTime.Now);          //HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString());        }        return;      }      else if (!_isMap)      {        //不重启程序,修改静态字段值        foreach (var item in CacheHelper._setValue)        {          item.Type.GetField(item.Name, Reflection.BindingFlags.Static | Reflection.BindingFlags.NonPublic).SetValue(null, item.Value);        }      }      _isMap = true;      CacheHelper._assembly.Flush();      CacheHelper._setValue.Clear();    }#if DEBUG    /// <summary>    /// 结束注入    /// </summary>    public static void End(string testPath)    {      bool reload = false;      foreach (var item in CacheHelper._assembly)      {        if (item.Value.Item2)        {          reload = true;          item.Value.Item1.MainModule.Types.Add(new TypeDefinition(_classType.Item1, _classType.Item2, Mono.Cecil.TypeAttributes.Class | Mono.Cecil.TypeAttributes.Public));          item.Value.Item1.Write(item.Key + testPath + ".dll");        }      }      if (reload)      {        _isMap = true;        if (HttpContext.Current != null)        {          //HttpRuntime.UnloadAppDomain();          HttpRuntime.UnloadAppDomain();          File.SetLastWriteTime(System.Web.Hosting.HostingEnvironment.MapPath("~/web.config"), DateTime.Now);          //HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString());        }        return;      }      else if (!_isMap)      {        foreach (var item in CacheHelper._setValue)        {          item.Type.GetField(item.Name, Reflection.BindingFlags.Static | Reflection.BindingFlags.NonPublic).SetValue(null, item.Value);        }      }      _isMap = true;    }#endif  }  /// <summary>  /// 支持注入  /// </summary>  public sealed class InjectMap<T> : InjectMap  {    InjectMap() { }    IInject<T> _inject;    internal static InjectMap<T> Create()    {      InjectMap<T> map = new InjectMap<T>();      map._inject = new InjectBase<T>();      return map;    }    /// <summary>    /// 注入属性值到指定类型中    /// </summary>    /// <typeparam name="TKey"></typeparam>    /// <param name="propertyName">属性名表达式</param>    /// <param name="propertyValue">属性值表达式</param>    /// <returns></returns>    public InjectMap<T> InjectProperty<TKey>(Expressions.Expression<Func<T, TKey>> propertyName, Expressions.Expression<Func<T, TKey>> propertyValue)    {      this._inject.InjectProperty(propertyName, propertyValue, InjectType.IgnoreOldValue);      return this;    }    /// <summary>    /// 注入属性值到指定类型中    /// </summary>    /// <typeparam name="TKey"></typeparam>    /// <param name="propertyName">属性名表达式</param>    /// <param name="propertyValue">属性值表达式</param>    /// <param name="type">注入属性选项</param>    /// <returns></returns>    public InjectMap<T> InjectProperty<TKey>(Expressions.Expression<Func<T, TKey>> propertyName, Expressions.Expression<Func<T, TKey>> propertyValue, InjectType type)    {      this._inject.InjectProperty(propertyName, propertyValue, type);      return this;    }  }}

 

测试:

 

  public class TestClass  {    public string Name { get; set; }    public int Id { get; set; }    public bool IsDeleted { get; set; }  }

 

Application_Start中执行代码:

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Web;namespace Dai.CommonLib.WebTest.Models{  class Register : IRegister  {    void IRegister.Register()    {      InjectMap.CreateMap<TestClass>().InjectProperty(o => o.Name, o => "test").InjectProperty(o => o.IsDeleted, o => !string.IsNullOrEmpty(o.Name));      InjectMap.End();    }  }}

 

控制器代码:

using Dai.CommonLib.WebTest.Models;using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace Dai.CommonLib.WebTest.Controllers{  public class HomeController : Controller  {    // GET: Home    public ActionResult Index()    {      TestClass testClass = new TestClass();      return Content(testClass.ToJson());    }  }}

 

看看效果

 

第一次访问:

 

{"Name":null,"Id":0,"IsDeleted":false}

 

 

此时程序会重启,并且Mono.Cecil会修改已生成好的程序集(如果没有修改过的话)

 

第二次及以后的访问:

{"Name":"test","Id":0,"IsDeleted":true}

 

这时候程序集的IL代码已经被修改了

 

 

优点:使用方便,可以省去一些麻烦

 

缺点:目前来看应用场景并不多,并且无法调试(因为程序集与源代码不匹配)!!!

 

不管怎么说,效果是有的