/// <summary> /// Create a singleton field used to store parameter information for the provided method. /// </summary> /// <param name="method">The method weaver.</param> /// <param name="param">The parameter.</param> /// <returns></returns> public Variable CreateParameterInfo(MethodEmitter method, ParameterReference param) { var parent = method.Parent.Target.IsNotPublic ? method.Parent : CreateTypeContainer(method.Parent.Target); var type = method.Parent.Target; var id = method.Target.GetHashString(); var name = $"<{method.Target.Name}${id}${param.Index}>k__ParameterInfo"; var existing = parent.GetField(name, Context.Finder.ParameterInfo, toStatic: true); if (existing != null) { return(existing); } var field = parent.EmitField(name, Context.Finder.ParameterInfo, toStatic: true, toPublic: true); var il = parent.GetStaticConstructor().GetIL(); il.Emit(Codes.Nop); il.Emit(Codes.LoadToken(type.HasGenericParameters ? method.Target : method.Target.GetGeneric())); il.Emit(Codes.LoadToken(type.GetGeneric())); il.Emit(Codes.InvokeStatic(Context.Finder.MethodBaseGetMethodFromHandleAndType)); il.Emit(Codes.Invoke(Context.Finder.MethodBaseGetParameters)); il.Emit(Codes.Int(param.Index)); il.Emit(Codes.LoadArray); il.Emit(Codes.Store(field)); return(field); }
/// <summary> /// Create a singleton field used to store property information for the provided property. /// </summary> /// <param name="property">The property weaver.</param> /// <returns></returns> public Variable CreatePropertyInfo(PropertyEmitter property) { var parent = property.Parent.Target.IsNotPublic ? property.Parent : CreateTypeContainer(property.Parent.Target); var type = property.Parent.Target; var sta = (property.Target.GetMethod ?? property.Target.SetMethod).IsStatic; var name = $"<{property.Target.Name}>k__PropertyInfo"; var existing = parent.GetField(name, Context.Finder.PropertyInfo, toStatic: true); if (existing != null) { return(existing); } var field = parent.EmitField(name, Context.Finder.PropertyInfo, toStatic: true, toPublic: true); var flags = BindingFlags.NonPublic | BindingFlags.Public | (sta ? BindingFlags.Static : BindingFlags.Instance); var il = parent.GetStaticConstructor().GetIL(); il.Emit(Codes.Nop); il.Emit(Codes.LoadToken(type.GetGeneric())); il.Emit(Codes.InvokeStatic(Context.Finder.TypeGetTypeFromHandle)); il.Emit(Codes.String(property.Target.Name)); il.Emit(Codes.Int((int)flags)); il.Emit(Codes.Invoke(Context.Finder.TypeGetProperty)); il.Emit(Codes.Store(field)); return(field); }
/// <summary> /// Weaves the constructor interceptors for a provided type and interceptor information. /// </summary> /// <param name="weaver">The weaver.</param> /// <param name="item">The interceptors.</param> public void WeaveConstructorInterceptors(TypeEmitter weaver, ConstructorInterceptorInfo item) { var constructors = weaver.GetConstructors(); foreach (var init in item.Initializers) { var parameters = init.Parameters; if (parameters.Any(p => !p.IsOptional)) { throw new NotSupportedException($"Cannot use constructor injection against a method with non-optional parameters"); } var after = init.GetAttribute(Context.Finder.IInjectAfterInitializer); var before = init.GetAttribute(Context.Finder.IInjectBeforeInitializer); if (init.HasGenericParameters) { throw new NotSupportedException($"Cannot use constructor injection against a generic method"); } foreach (var ctor in constructors) { var il = ctor.GetIL(); var st = init.IsStatic; il.Body.SimplifyMacros(); il.Insert = CodeInsertion.Before; il.Position = before != null ? (il.GetConstructorBaseOrThis()?.Next ?? il.GetFirst()) : il.GetLast(); if (!st) { il.Emit(Codes.This); } var type = ctor.Parent.Target.GetGeneric(); var method = (MethodReference)init; if (type.IsGenericInstance) { var generic = (GenericInstanceType)type; method = init.MakeGeneric(generic.GenericArguments.ToArray()); } foreach (var param in parameters) { il.Emit(Codes.Load(param.Constant)); } il.Emit(st ? Codes.InvokeStatic(method) : Codes.Invoke(method)); if (method.IsReturn()) { il.Emit(Codes.Pop); } il.Body.InitLocals = true; il.Body.OptimizeMacros(); } if (after != null) { init.CustomAttributes.Remove(after); } if (before != null) { init.CustomAttributes.Remove(before); } } }