/// <summary> /// Creates a multi-singleton field used to retain an instance of an attribute. /// </summary> /// <param name="emitter">The type weaver.</param> /// <param name="attribute">The attribute.</param> /// <param name="member">The member.</param> /// <returns></returns> public Variable CreateAttributeMultiSingleton(TypeEmitter emitter, CustomAttribute attribute, MemberReference member) { var index = Interlocked.Increment(ref id); var type = attribute.AttributeType; var name = $"<{type.Name}${index}>k__Attribute"; var field = singletons.EmitField(name, type, toStatic: true, toPublic: true); var emit = singletons.GetStaticConstructor(); var il = emit.GetIL(); il.Emit(Codes.Nop); foreach (var arg in attribute.ConstructorArguments) { CreateAttributeParameter(emit, attribute, arg); } il.Emit(Codes.Create(attribute.Constructor)); il.Emit(Codes.Store(field)); foreach (var prop in attribute.Properties) { CreateAttributeProperty(emit, attribute, field, prop); } CreateAttributeRequirements(il, attribute, member, field, true); return(field); }
/// <summary> /// Create an adhoc variable used to retain an instance of an attribute. /// </summary> /// <param name="method">The method weaver.</param> /// <param name="attribute">The attribute.</param> /// <param name="member">The member.</param> /// <returns></returns> public Variable CreateAttributeAdhoc(MethodEmitter method, CustomAttribute attribute, MemberReference member) { var type = attribute.AttributeType; var variable = method.EmitLocal(type); var il = method.GetIL(); foreach (var arg in attribute.ConstructorArguments) { CreateAttributeParameter(method, attribute, arg); } il.Emit(Codes.Create(attribute.Constructor)); il.Emit(Codes.Store(variable)); if (attribute.HasInterface(Context.Finder.IInstanceAware) && !method.Target.IsStatic) { il.Emit(Codes.Load(variable)); il.Emit(Codes.This); il.Emit(Codes.Invoke(Context.Finder.InstanceAwareInstanceSet)); } foreach (var prop in attribute.Properties) { CreateAttributeProperty(method, attribute, variable, prop); } CreateAttributeRequirements(il, attribute, member, variable, false); return(variable); }
/// <summary> /// Creates an multi-instance-level field used to retain an instance of an attribute. /// </summary> /// <param name="emitter">The type weaver.</param> /// <param name="attribute">The attribute.</param> /// <param name="member">The member.</param> /// <returns></returns> public Variable CreateAttributeMultiInstanced(TypeEmitter emitter, CustomAttribute attribute, MemberReference member) { var index = Interlocked.Increment(ref id); var type = attribute.AttributeType; var name = $"<{type.Name}${index}>k__Attribute"; var existing = emitter.GetField(name, type, toStatic: false); if (existing != null) { return(existing); } var field = emitter.EmitField(name, type); foreach (var ctor in emitter.GetConstructors()) { var il = ctor.GetIL(); il.Insert = CodeInsertion.Before; il.Position = il.GetConstructorBaseOrThis()?.Next ?? il.GetFirst(); il.Emit(Codes.Nop); il.Emit(Codes.This); foreach (var arg in attribute.ConstructorArguments) { CreateAttributeParameter(ctor, attribute, arg); } il.Emit(Codes.Create(attribute.Constructor)); il.Emit(Codes.Store(field)); if (attribute.HasInterface(Context.Finder.IInstanceAware)) { il.Emit(Codes.ThisIf(field)); il.Emit(Codes.Load(field)); il.Emit(Codes.This); il.Emit(Codes.Invoke(Context.Finder.InstanceAwareInstanceSet)); } foreach (var prop in attribute.Properties) { CreateAttributeProperty(ctor, attribute, field, prop); } CreateAttributeRequirements(il, attribute, member, field, false); } return(field); }
private static async Task StoreData(string ninConnectionString, string urlAlleKoder, string urlVariasjoner, string redList) { var ninMemApiDataLocation = _configuration["NinMemApiData"]; if (!Directory.Exists(ninMemApiDataLocation)) { throw new DirectoryNotFoundException("Directory given in appsettings.json for \"NinMemApiData\" not found"); } var koder = GetKoder(urlAlleKoder, urlVariasjoner); var natureAreas = await DataLoaders.NatureAreas.NatureAreaLoader.Load(ninConnectionString); var descriptionVariables = await DescriptionVariableLoader.Load(ninConnectionString, Codes.Create(koder.variasjonKoder)); var natureAreaTypes = await NatureAreaTypeLoader.Load(ninConnectionString, Codes.Create(koder.alleKoder)); var redlistData = await RedlistLoader.Load(ninConnectionString, redList); var geographicalData = await GeographicalAreaLoader.Load(ninConnectionString); var taxons = TaxonLoader.Get(ninConnectionString); var codetree = new WebClient().DownloadString(_configuration["Kodetre"]); var natureAreaVariables = await NatureAreaVariablesLoader.Load(ninConnectionString); //// TODO: uncomment this when TaxonTraits is back //var taxonTraits = File.ReadAllText("..\\..\\..\\Data\\taxonTraits.json"); var localStorage = new LocalStorage(ninMemApiDataLocation); await Task.WhenAll( localStorage.Store(StorageKeys.NatureAreas, natureAreas), localStorage.Store(StorageKeys.NatureAreaDescriptionVariables, descriptionVariables), localStorage.Store(StorageKeys.NatureAreaTypes, natureAreaTypes), localStorage.Store(StorageKeys.NatureAreaRedlistCategories, redlistData.categories), localStorage.Store(StorageKeys.NatureAreaRedlistThemes, redlistData.themes), localStorage.Store(StorageKeys.NatureAreaGeographicalAreaData, geographicalData), localStorage.Store(StorageKeys.Taxons, taxons.Values.ToList()), localStorage.Store(StorageKeys.CodeTree, codetree), localStorage.Store(StorageKeys.NatureAreaVariables, natureAreaVariables) //// TODO: uncomment this when TaxonTraits is back //localStorage.Store(StorageKeys.TaxonTraits, taxonTraits) ); }
/// <summary> /// Weaves the interception logic of a property. /// </summary> /// <param name="parent"></param> /// <param name="item"></param> public void WeavePropertyInterceptors(TypeEmitter parent, PropertyInterceptorInfo item) { var property = item.Property; var getter = property.GetMethod != null ? new MethodEmitter(parent, property.GetMethod) : null; var setter = property.SetMethod != null ? new MethodEmitter(parent, property.SetMethod) : null; var count = item.Interceptors.Length; var weaver = new PropertyEmitter(parent, property); if (count == 0) { return; } var gInterceptors = new Variable[count]; var sInterceptors = new Variable[count]; for (int i = 0; i < count; i++) { var variables = CreateAttribute(weaver, getter, setter, item.Interceptors[i], item.Field); gInterceptors[i] = variables[0]; sInterceptors[i] = variables[1]; } var hasGetter = gInterceptors.Any(i => i != null); var hasSetter = sInterceptors.Any(i => i != null); var type = property.PropertyType; var info = CreatePropertyInfo(weaver); var field = property.GetBackingField(); var backing = (Variable)null; if (field != null) { var def = field.Resolve(); def.Attributes &= ~Mono.Cecil.FieldAttributes.InitOnly; backing = new Variable(def); } if (getter != null && hasGetter) { var il = getter.GetIL(); var result = getter.EmitLocal(property.PropertyType); il.Body.SimplifyMacros(); il.Position = il.GetFirst(); il.Insert = CodeInsertion.Before; if (backing != null) { il.Emit(Codes.ThisIf(backing)); il.Emit(Codes.Load(backing)); il.Emit(Codes.Store(result)); } else { if (type.IsValueType) { il.Emit(Codes.Address(result)); il.Emit(Codes.Init(type)); } else { il.Emit(Codes.Null); il.Emit(Codes.Store(result)); } } il.Try(); var leave = WeaveMethodReturnsRoute(getter, result, true); var cancel = il.EmitLabel(); var args = il.EmitLocal(Context.Finder.PropertyInterceptionArgs); il.Emit(getter.Target.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(info)); il.Emit(Codes.Load(result)); il.Emit(Codes.Box(type)); il.Emit(Codes.Create(Context.Finder.PropertyInterceptionArgsCtor)); il.Emit(Codes.Store(args)); for (int i = 0; i < count; i++) { var inc = gInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyGetInterceptorOnGet)); } il.Position = leave; il.Finally(); for (int i = 0; i < count; i++) { var inc = gInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyGetInterceptorOnExit)); } il.Mark(cancel); il.EndTry(); il.Insert = CodeInsertion.After; if (setter != null || backing != null) { var unchanged = il.EmitLabel(); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsIsDirtyGet)); il.Emit(Codes.IfFalse(unchanged)); if (!getter.Target.IsStatic) { il.Emit(Codes.This); } if (backing == null) { var pcount = setter.Target.Parameters.Count - 1; for (int i = 0; i < pcount; i++) { il.Emit(Codes.Arg(setter.Target.Parameters[i])); } } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(type)); if (backing != null) { il.Emit(Codes.Store(backing)); } else { il.Emit(Codes.Invoke(setter.Target)); } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(type)); il.Emit(Codes.Store(result)); il.Emit(Codes.Nop); il.Mark(unchanged); } il.Emit(Codes.Load(result)); il.Body.InitLocals = true; il.Body.OptimizeMacros(); } if (setter != null && hasSetter) { var il = setter.GetIL(); il.Body.SimplifyMacros(); il.Position = il.GetFirst(); il.Insert = CodeInsertion.Before; var args = il.EmitLocal(Context.Finder.PropertyInterceptionArgs); var cancel = il.EmitLabel(); var argument = new Variable(setter.Target.Parameters.Last()); il.Try(); il.Emit(setter.Target.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(info)); il.Emit(Codes.Load(argument)); il.Emit(Codes.Box(type)); il.Emit(Codes.Create(Context.Finder.PropertyInterceptionArgsCtor)); il.Emit(Codes.Store(args)); for (int i = 0; i < count; i++) { var inc = sInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertySetInterceptorOnSet)); } il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsIsDirtyGet)); il.Emit(Codes.IfFalse(cancel)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertyInterceptionArgsValueGet)); il.Emit(Codes.Unbox(argument.Type)); il.Emit(Codes.Store(argument)); il.Emit(Codes.Nop); il.Position = il.Position.Previous; il.Mark(cancel); il.Position = il.GetLast(); il.Emit(Codes.Leave(il.Position)); il.Finally(); for (int i = 0; i < count; i++) { var inc = sInterceptors[i]; if (inc == null) { continue; } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); il.Emit(Codes.Load(args)); il.Emit(Codes.Invoke(Context.Finder.PropertySetInterceptorOnExit)); } il.EndTry(); il.Body.InitLocals = true; il.Body.OptimizeMacros(); } }
/// <summary> /// Weaves the interception logic of a method. /// </summary> /// <param name="weaver">The method weaver.</param> /// <param name="item">The method information.</param> public void WeaveMethodInterceptors(MethodEmitter weaver, MethodInterceptorInfo item) { weaver.Body.SimplifyMacros(); var pAttributes = item.Parameters.SelectMany(p => p.Attributes.Select(a => new { p.Index, Attribute = a })).ToArray(); var mAttributes = item.MethodInterceptors; var rAttributes = item.ReturnInterceptors; var pInterceptors = new Variable[pAttributes.Length]; var mInterceptors = new Variable[item.MethodInterceptors.Length]; var rInterceptors = new Variable[rAttributes.Length]; var needsEnter = mAttributes.Any(m => m.HasRequiredMethod(Context.Finder.MethodInterceptorOnEnter)); var needsCatch = mAttributes.Any(m => m.HasRequiredMethod(Context.Finder.MethodInterceptorOnException)); var needsExit = mAttributes.Any(m => m.HasRequiredMethod(Context.Finder.MethodInterceptorOnExit)); var needsParams = pAttributes.Any(m => m.Attribute.HasRequiredMethod(Context.Finder.ParameterInterceptorOnEnter)); var needsReturns = rAttributes.Any(m => m.HasRequiredMethod(Context.Finder.MethodReturnInterceptorOnReturn)); var needsMethodArgs = mAttributes.Any(m => { return(m.AttributeType.GetMethod(Context.Finder.MethodInterceptorOnEnter).UsesParameter(0) || m.AttributeType.GetMethod(Context.Finder.MethodInterceptorOnException).UsesParameter(0) || m.AttributeType.GetMethod(Context.Finder.MethodInterceptorOnExit).UsesParameter(0)); }); var needsParamArgs = pAttributes.Any(m => m.Attribute.AttributeType.GetMethod(Context.Finder.ParameterInterceptorOnEnter).UsesParameter(0)); var needsReturnsArgs = rAttributes.Any(m => m.AttributeType.GetMethod(Context.Finder.MethodReturnInterceptorOnReturn).UsesParameter(0)); var needsMethodCopyArgs = mAttributes.Any(m => m.GetAttribute(Context.Finder.CompilationOptionsAttribute)?.GetProperty("CopyArguments", notFound: false) ?? false); if (!needsEnter && !needsCatch && !needsExit && !needsParams && !needsReturns) { return; } var method = weaver.Target; var il = weaver.GetIL(); il.Position = il.GetFirst(); il.Insert = CodeInsertion.Before; var result = (Variable)null; if (weaver.Target.IsReturn()) { var type = weaver.Target.ReturnType; result = weaver.EmitLocal(type); if (type.IsValueType) { il.Emit(Codes.Address(result)); il.Emit(Codes.Init(type)); } else { il.Emit(Codes.Null); il.Emit(Codes.Store(result)); } } var leave = WeaveMethodReturnsRoute(weaver, result, mInterceptors.Length > 0); var cancel = il.EmitLabel(); for (int i = 0, count = pInterceptors.Length; i < count; i++) { pInterceptors[i] = CreateAttribute(weaver, pAttributes[i].Attribute); } for (int i = 0, count = mInterceptors.Length; i < count; i++) { mInterceptors[i] = CreateAttribute(weaver, mAttributes[i]); } for (int i = 0, count = rInterceptors.Length; i < count; i++) { rInterceptors[i] = CreateAttribute(weaver, rAttributes[i]); } foreach (var attribute in mAttributes) { weaver.Target.CustomAttributes.Remove(attribute); } foreach (var attribute in pAttributes) { if (attribute.Index == -1) { weaver.Target.CustomAttributes.Remove(attribute.Attribute); } else { weaver.Target.Parameters[attribute.Index].CustomAttributes.Remove(attribute.Attribute); } } foreach (var attribute in rAttributes) { weaver.Target.MethodReturnType.CustomAttributes.Remove(attribute); } foreach (var parameter in item.Parameters) { foreach (var attribute in parameter.Attributes) { if (parameter.Index == -1) { weaver.Target.CustomAttributes.Remove(attribute); } else { weaver.Target.Parameters[parameter.Index].CustomAttributes.Remove(attribute); } } } var hasMethod = mInterceptors.Length > 0; var hasParams = pInterceptors.Length > 0; var hasReturn = rInterceptors.Length > 0; var arguments = hasMethod ? CreateArgumentArray(weaver) : null; var invocation = CreateMethodInfo(weaver); var mEventArgs = hasMethod && needsMethodArgs?weaver.EmitLocal(Context.Finder.MethodInterceptionArgs, name : "methodEventArgs") : null; if (hasMethod || hasReturn) { if (hasMethod && needsMethodArgs) { il.Emit(method.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(arguments)); if (result == null) { il.Emit(Codes.Null); } else { il.Emit(Codes.Load(result)); il.Emit(Codes.Box(result.Type)); } il.Emit(Codes.Load(invocation)); il.Emit(Codes.Create(Context.Finder.MethodInterceptionArgsCtor)); il.Emit(Codes.Store(mEventArgs)); } il.Try(); } if (hasParams && needsParams) { var pEventArgs = needsParamArgs ? weaver.EmitLocal(Context.Finder.ParameterInterceptionArgs) : null; for (int i = 0, count = pInterceptors.Length; i < count; i++) { var inc = pInterceptors[i]; var parameters = pAttributes[i].Index == -1 ? method.Parameters.ToArray() : new[] { method.Parameters[pAttributes[i].Index] }; for (int j = 0, pCount = parameters.Length; j < pCount; j++) { var prm = parameters[j]; var pVariable = new Variable(prm); var pInfo = CreateParameterInfo(weaver, prm); var needsCopyArgs = pAttributes[i].Attribute.GetAttribute(Context.Finder.CompilationOptionsAttribute)?.GetProperty("CopyArguments", notFound: false) ?? false; if (needsParamArgs) { il.Emit(method.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(pInfo)); il.Emit(Codes.Arg(pVariable)); il.Emit(Codes.Box(prm.ParameterType)); il.Emit(Codes.Create(Context.Finder.ParameterInterceptionArgsCtor)); il.Emit(Codes.Store(pEventArgs)); } il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); if (needsParamArgs) { il.Emit(Codes.Load(pEventArgs)); } else { il.Emit(Codes.Null); } il.Emit(Codes.Invoke(Context.Finder.ParameterInterceptorOnEnter)); if (needsParamArgs && !prm.IsOut && needsCopyArgs) { il.Emit(Codes.Load(pEventArgs)); il.Emit(Codes.Invoke(Context.Finder.ParameterInterceptionArgsValueGet)); il.Emit(Codes.Unbox(prm.ParameterType)); il.Emit(Codes.Store(pVariable)); } } } } if (hasMethod || hasReturn) { if (hasMethod && needsEnter) { for (int i = 0, count = mInterceptors.Length; i < count; i++) { var inc = mInterceptors[i]; var att = mAttributes[i]; if (att.HasRequiredMethod("OnEnter")) { il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); if (needsMethodArgs) { il.Emit(Codes.Load(mEventArgs)); } else { il.Emit(Codes.Null); } il.Emit(Codes.Invoke(Context.Finder.MethodInterceptorOnEnter)); if (needsMethodArgs) { var proceed = il.EmitLabel(); il.Emit(Codes.Load(mEventArgs)); il.Emit(Codes.Invoke(Context.Finder.MethodInterceptionArgsCancelGet)); il.Emit(Codes.IfFalse(proceed)); if (result != null && needsMethodArgs) { il.Emit(Codes.Load(mEventArgs)); il.Emit(Codes.Invoke(Context.Finder.MethodInterceptionArgsReturnGet)); il.Emit(Codes.Unbox(result.Type)); il.Emit(Codes.Store(result)); } il.Emit(Codes.Leave(leave)); il.Mark(proceed); } } } if (needsMethodArgs && needsMethodCopyArgs && arguments != null) { CopyArgumentArrayToParameters(weaver, arguments); } } il.Position = leave; if (hasMethod && needsCatch) { var exception = il.EmitLocal(Context.Finder.Exception); il.Catch(exception); for (int i = 0, count = mInterceptors.Length; i < count; i++) { var inc = mInterceptors[i]; var att = mAttributes[i]; if (att.HasRequiredMethod("OnException")) { il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); if (needsMethodArgs) { il.Emit(Codes.Load(mEventArgs)); } else { il.Emit(Codes.Null); } il.Emit(Codes.Load(exception)); il.Emit(Codes.Invoke(Context.Finder.MethodInterceptorOnException)); } } if (needsExit || needsReturns) { il.Emit(Codes.Nop); il.Emit(Codes.Leave(leave)); } } if (needsExit || needsReturns) { il.Finally(leave); } if (hasMethod) { if (result != null && needsMethodArgs) { il.Emit(Codes.Load(mEventArgs)); il.Emit(Codes.Load(result)); il.Emit(Codes.Box(weaver.Target.ReturnType)); il.Emit(Codes.Invoke(Context.Finder.MethodInterceptionArgsReturnSet)); } if (needsExit) { for (int i = 0, count = mInterceptors.Length; i < count; i++) { var inc = mInterceptors[i]; var att = mAttributes[i]; if (att.HasRequiredMethod("OnExit")) { il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); if (needsMethodArgs) { il.Emit(Codes.Load(mEventArgs)); } else { il.Emit(Codes.Null); } il.Emit(Codes.Invoke(Context.Finder.MethodInterceptorOnExit)); } } } il.Mark(cancel); } if (hasReturn && needsReturns && result != null) { var rEventArgs = needsReturnsArgs ? il.EmitLocal(Context.Finder.MethodReturnInterceptionArgs) : null; if (needsReturnsArgs) { il.Emit(method.IsStatic ? Codes.Null : Codes.This); il.Emit(Codes.Load(result)); il.Emit(Codes.Box(result.Type)); il.Emit(Codes.Load(invocation)); il.Emit(Codes.Create(Context.Finder.MethodReturnInterceptionArgsCtor)); il.Emit(Codes.Store(rEventArgs)); } for (int i = 0, count = rInterceptors.Length; i < count; i++) { var inc = rInterceptors[i]; var att = rAttributes[i]; if (att.HasRequiredMethod("OnReturn")) { il.Emit(Codes.ThisIf(inc)); il.Emit(Codes.Load(inc)); if (needsReturnsArgs) { il.Emit(Codes.Load(rEventArgs)); } else { il.Emit(Codes.Null); } il.Emit(Codes.Invoke(Context.Finder.MethodReturnInterceptorOnReturn)); } } if (needsReturnsArgs) { il.Emit(Codes.Load(rEventArgs)); il.Emit(Codes.Invoke(Context.Finder.MethodReturnInterceptionArgsValueGet)); il.Emit(Codes.Unbox(result.Type)); il.Emit(Codes.Store(result)); } } if (!needsExit && !needsReturns) { il.Emit(Codes.Nop); il.Emit(Codes.Leave(leave)); } il.EndTry(); il.Insert = CodeInsertion.After; if (hasMethod && arguments != null) { CopyArgumentArrayToReferences(weaver, arguments); } if (hasMethod && needsMethodArgs && result != null) { il.Emit(Codes.Nop); il.Emit(Codes.Load(mEventArgs)); il.Emit(Codes.Invoke(Context.Finder.MethodInterceptionArgsReturnGet)); il.Emit(Codes.Unbox(weaver.Target.ReturnType)); } else if (hasMethod && result != null) { il.Emit(Codes.Nop); il.Emit(Codes.Load(result)); } } weaver.Body.InitLocals = true; weaver.Body.OptimizeMacros(); }