/// <summary> /// Creates a lambda compiler that will compile into the provided MethodBuilder /// </summary> private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method) { var scope = tree.Scopes[lambda]; var hasClosureArgument = scope.NeedsClosure; var paramTypes = GetParameterTypes(lambda, hasClosureArgument ? typeof(Closure) : null); method.SetReturnType(lambda.ReturnType); method.SetParameters(paramTypes); var parameters = lambda.Parameters; // parameters are index from 1, with closure argument we need to skip the first arg var startIndex = hasClosureArgument ? 2 : 1; for (int i = 0, n = parameters.Count; i < n; i++) { method.DefineParameter(i + startIndex, ParameterAttributes.None, parameters[i].Name); } _tree = tree; _lambda = lambda; _typeBuilder = (TypeBuilder)method.DeclaringType; _method = method; _hasClosureArgument = hasClosureArgument; IL = method.GetILGenerator(); // These are populated by AnalyzeTree/VariableBinder _scope = scope; _boundConstants = tree.Constants[lambda]; InitializeMethod(); }
/// <summary> /// 定义代理类型。 /// </summary> private void DefineProxyType() { var baseType = this.BaseType; var module = ModuleProvider.ProxyTypesModule; var baseNamespace = baseType.Namespace; var @namespace = (baseNamespace is not null) ? $"{baseNamespace}." : ""; var baseTypeNames = new List <string>(); for (var nestedType = baseType; nestedType is not null; nestedType = nestedType.DeclaringType) { baseTypeNames.Insert(0, nestedType.Name); } var typeNames = baseTypeNames.ToArray(); var joinedTypeNames = string.Join("-", typeNames); var baseGenericArgumentNames = Array.ConvertAll( baseType.GetGenericArguments(), genericArgument => genericArgument.ToString()); var genericArgumentNames = Array.ConvertAll( baseGenericArgumentNames, name => name.Replace('.', '-').Replace('+', '-')); var joinedGenericArgumentNames = baseType.IsGenericType ? $"<{string.Join(",", genericArgumentNames)}>" : ""; var fullName = $"{@namespace}$WrapProxy@{joinedTypeNames}{joinedGenericArgumentNames}" + $"#{baseType.TypeHandle.Value.ToString()}"; var parent = typeof(object); var interfaces = new[] { baseType }.Concat(baseType.GetInterfaces()).ToArray(); var type = module.DefineType(fullName, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit, parent, interfaces); this.ProxyTypeBuilder = type; }
internal TypeBuilder?GetRegisteredType(ITypeName name) { TypeBuilder?result = null; name_cache.TryGetValue(name, out result); return(result); }
/// <inheritdoc /> public IActionBuilder Add(MethodInfo action, ThingActionAttribute?attribute) { if (_thingType == null || _module == null) { throw new InvalidOperationException($"ThingType is null, call {nameof(SetThingType)} before add"); } if (_actions == null || _option == null) { throw new InvalidOperationException($"ThingOption is null, call {nameof(SetThingOption)} before add"); } if (_input != null) { _input.CreateType(); var(actionInfoBuilder, inputProperty) = CreateActionInfo(_action !, _input, _thingType, _name !); var factory = CreateActionInfoFactory(actionInfoBuilder, _input, inputProperty); _actions.Add(_name !, new ActionCollection( new SystemTextJsonInputConvertible(_jsonConvertibles !), new InputJsonSchemaValidation(_jsonSchemaValidations !), new InputConvertible(_convertibles !), (IActionInformationFactory)Activator.CreateInstance(factory) !)); } _jsonConvertibles = new Dictionary <string, IJsonConvertible>(_option.IgnoreCase ? StringComparer.OrdinalIgnoreCase : null); _jsonSchemaValidations = new Dictionary <string, IJsonSchemaValidation>(_option.IgnoreCase ? StringComparer.OrdinalIgnoreCase : null); _convertibles = new Dictionary <string, IConvertible?>(_option.IgnoreCase ? StringComparer.OrdinalIgnoreCase : null); _name = attribute?.Name ?? action.Name; _action = action; _input = _module.DefineType($"{action.Name}Input", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoClass); return(this); }
internal void CreateGlobalType() { if (global_type == null) { global_type = new TypeBuilder(this, 0, 1); } }
public void CheckTypeNameConflict(string strTypeName, TypeBuilder?enclosingType) { for (int i = 0; i < _moduleBuilderList.Count; i++) { ModuleBuilder curModule = _moduleBuilderList[i]; curModule.CheckTypeNameConflict(strTypeName, enclosingType); } }
public XmlILModule(TypeBuilder typeBldr) { _typeBldr = typeBldr; _emitSymbols = false; _useLRE = false; // Index all methods added to this module by unique name _methods = new Hashtable(); }
private void _createContainerTypeIfNotCreated() { if (m_containerType != null) { return; } m_containerType = m_assemblyBuilder.defineType( new TypeName(NameMangler.INTERNAL_NAMESPACE, "Helpers"), TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic ); }
/// <inheritdoc /> public IEventBuilder SetThingType(Type thingType) { _thingType = thingType; var baseName = $"{thingType.Name}EventBinder"; var assemblyName = new AssemblyName($"{baseName}Assembly"); var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule($"{baseName}Module"); _builder = moduleBuilder.DefineType(baseName, TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public, null, null); return(this); }
/// <summary> /// Creates a lambda compiler for an inlined lambda /// </summary> private LambdaCompiler( LambdaCompiler parent, LambdaExpression lambda, InvocationExpression invocation) { _tree = parent._tree; _lambda = lambda; _method = parent._method; IL = parent.IL; _hasClosureArgument = parent._hasClosureArgument; _typeBuilder = parent._typeBuilder; // inlined scopes are associated with invocation, not with the lambda _scope = _tree.Scopes[invocation]; _boundConstants = parent._boundConstants; }
private TypeBuilder?GetMaybeNested(TypeBuilder t, IEnumerable <ITypeName> nested) { TypeBuilder?result = t; foreach (ITypeName pname in nested) { if (result.subtypes == null) { return(null); } result = search_nested_in_array(result.subtypes, result.subtypes.Length, pname); if (result == null) { return(null); } } return(result); }
// SxS note: AssemblyBuilder.DefineDynamicModule() below may be using name which is not SxS safe. // This file is written only for internal tracing/debugging purposes. In retail builds persistAsm // will be always false and the file should never be written. As a result it's fine just to suppress // the SxS warning. public XmlILModule(bool useLRE, bool emitSymbols) { AssemblyName asmName; AssemblyBuilder asmBldr; ModuleBuilder modBldr; Debug.Assert(!(useLRE && emitSymbols)); _useLRE = useLRE; _emitSymbols = emitSymbols; // Index all methods added to this module by unique name _methods = new Hashtable(); if (!useLRE) { // 1. If assembly needs to support debugging, then it must be saved and re-loaded (rule of CLR) // 2. Get path of temp directory, where assembly will be saved // 3. Never allow assembly to Assert permissions asmName = CreateAssemblyName(); asmBldr = AssemblyBuilder.DefineDynamicAssembly( asmName, AssemblyBuilderAccess.Run); // Add custom attribute to assembly marking it as security transparent so that Assert will not be allowed // and link demands will be converted to full demands. asmBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.Transparent, Array.Empty <object>())); if (emitSymbols) { // Add DebuggableAttribute to assembly so that debugging is a better experience DebuggingModes debuggingModes = DebuggingModes.Default | DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggingModes.DisableOptimizations; asmBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.Debuggable, new object[] { debuggingModes })); } // Create ModuleBuilder modBldr = asmBldr.DefineDynamicModule("System.Xml.Xsl.CompiledQuery"); _typeBldr = modBldr.DefineType("System.Xml.Xsl.CompiledQuery.Query", TypeAttributes.Public); } }
/// <summary> /// Once all methods have been defined, CreateModule must be called in order to "bake" the methods within /// this module. /// </summary> public void BakeMethods() { Type typBaked; Hashtable methodsBaked; if (!_useLRE) { typBaked = _typeBldr !.CreateType(); // Replace all MethodInfos in this.methods methodsBaked = new Hashtable(_methods.Count); foreach (string methName in _methods.Keys) { methodsBaked[methName] = typBaked.GetMethod(methName, BindingFlags.NonPublic | BindingFlags.Static); } _methods = methodsBaked; // Release TypeBuilder and symbol writer resources _typeBldr = null; } }
public override Type?GetType(string className, bool throwOnError, bool ignoreCase) { if (className == null) { throw new ArgumentNullException(nameof(className)); } if (className.Length == 0) { throw new ArgumentException(SR.Argument_EmptyName, nameof(className)); } TypeBuilder?result = null; if (types == null && throwOnError) { throw new TypeLoadException(className); } TypeSpec ts = TypeSpec.Parse(className); if (!ignoreCase) { ITypeName displayNestedName = ts.TypeNameWithoutModifiers(); name_cache.TryGetValue(displayNestedName, out result); } else { if (types != null) { result = search_in_array(types, num_types, ts.Name !); } if (!ts.IsNested && result != null) { result = GetMaybeNested(result, ts.Nested); } } if ((result == null) && throwOnError) { throw new TypeLoadException(className); } if (result != null && (ts.HasModifiers || ts.IsByRef)) { Type mt = result; if (result is TypeBuilder) { var tb = result as TypeBuilder; if (tb.is_created) { mt = tb.CreateType() !; } } foreach (IModifierSpec mod in ts.Modifiers) { if (mod is PointerSpec) { mt = mt.MakePointerType() !; } else if (mod is IArraySpec) { var spec = (mod as IArraySpec) !; if (spec.IsBound) { return(null); } if (spec.Rank == 1) { mt = mt.MakeArrayType(); } else { mt = mt.MakeArrayType(spec.Rank); } } } if (ts.IsByRef) { mt = mt.MakeByRefType(); } result = mt as TypeBuilder; if (result == null) { return(mt); } } if (result != null && result.is_created) { return(result.CreateType()); } else { return(result); } }
/// <summary> /// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed. /// </summary> // SxS Note: The way the trace file names are created (hardcoded) is NOT SxS safe. However the files are // created only for internal tracing purposes. In addition XmlILTrace class is not compiled into retail // builds. As a result it is fine to suppress the FxCop SxS warning. // TODO-NULLABLE: missing [return: NotNullIfNull("typeBldr")] public XmlILCommand?Generate(QilExpression query, TypeBuilder?typeBldr) { _qil = query; bool useLRE = ( !_qil.IsDebug && (typeBldr == null) #if DEBUG && !XmlILTrace.IsEnabled // Dump assembly to disk; can't do this when using LRE #endif ); bool emitSymbols = _qil.IsDebug; // In debug code, ensure that input QIL is correct QilValidationVisitor.Validate(_qil); #if DEBUG // Trace Qil before optimization XmlILTrace.WriteQil(_qil, "qilbefore.xml"); // Trace optimizations XmlILTrace.TraceOptimizations(_qil, "qilopt.xml"); #endif // Optimize and annotate the Qil graph _optVisitor = new XmlILOptimizerVisitor(_qil, !_qil.IsDebug); _qil = _optVisitor.Optimize(); // In debug code, ensure that output QIL is correct QilValidationVisitor.Validate(_qil); #if DEBUG // Trace Qil after optimization XmlILTrace.WriteQil(_qil, "qilafter.xml"); #endif // Create module in which methods will be generated if (typeBldr != null) { _module = new XmlILModule(typeBldr); } else { _module = new XmlILModule(useLRE, emitSymbols); } // Create a code generation helper for the module; enable optimizations if IsDebug is false _helper = new GenerateHelper(_module, _qil.IsDebug); // Create helper methods CreateHelperFunctions(); // Create metadata for the Execute function, which is the entry point to the query // public static void Execute(XmlQueryRuntime); MethodInfo methExec = _module.DefineMethod("Execute", typeof(void), Array.Empty <Type>(), Array.Empty <string>(), XmlILMethodAttributes.NonUser); // Create metadata for the root expression // public void Root() Debug.Assert(_qil.Root != null); XmlILMethodAttributes methAttrs = (_qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; MethodInfo methRoot = _module.DefineMethod("Root", typeof(void), Array.Empty <Type>(), Array.Empty <string>(), methAttrs); // Declare all early bound function objects foreach (EarlyBoundInfo info in _qil.EarlyBoundTypes) { _helper.StaticData.DeclareEarlyBound(info.NamespaceUri, info.EarlyBoundType); } // Create metadata for each QilExpression function that has at least one caller CreateFunctionMetadata(_qil.FunctionList); // Create metadata for each QilExpression global variable and parameter CreateGlobalValueMetadata(_qil.GlobalVariableList); CreateGlobalValueMetadata(_qil.GlobalParameterList); // Generate Execute method GenerateExecuteFunction(methExec, methRoot); // Visit the QilExpression graph _xmlIlVisitor = new XmlILVisitor(); _xmlIlVisitor.Visit(_qil, _helper, methRoot); // Collect all static information required by the runtime XmlQueryStaticData staticData = new XmlQueryStaticData( _qil.DefaultWriterSettings, _qil.WhitespaceRules, _helper.StaticData ); // Create static constructor that initializes XmlQueryStaticData instance at runtime if (typeBldr != null) { CreateTypeInitializer(staticData); // Finish up creation of the type _module.BakeMethods(); return(null); } else { // Finish up creation of the type _module.BakeMethods(); // Create delegate over "Execute" method ExecuteDelegate delExec = (ExecuteDelegate)_module.CreateDelegate("Execute", typeof(ExecuteDelegate)); return(new XmlILCommand(delExec, staticData)); } }
/// <summary> /// Helper to ensure the type name is unique underneath assemblyBuilder. /// </summary> internal void CheckTypeNameConflict(string strTypeName, TypeBuilder?enclosingType) { _manifestModuleBuilder.CheckTypeNameConflict(strTypeName, enclosingType); }
private static MethodBuilder?GetFieldGetMethod( TypeBuilder?proxyTypeBuilder, Type targetType, MemberInfo proxyMember, FieldInfo targetField, FieldInfo?instanceField) { string proxyMemberName = proxyMember.Name; Type proxyMemberReturnType = proxyMember is PropertyInfo pinfo ? pinfo.PropertyType : proxyMember is FieldInfo finfo ? finfo.FieldType : typeof(object); MethodBuilder?proxyMethod = proxyTypeBuilder?.DefineMethod( "get_" + proxyMemberName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.Virtual, proxyMemberReturnType, Type.EmptyTypes); LazyILGenerator il = new LazyILGenerator(proxyMethod?.GetILGenerator()); Type returnType = targetField.FieldType; // Load the instance if (!targetField.IsStatic) { il.Emit(OpCodes.Ldarg_0); if (instanceField is not null) { il.Emit(instanceField.FieldType.IsValueType ? OpCodes.Ldflda : OpCodes.Ldfld, instanceField); } } // Load the field value to the stack if (UseDirectAccessTo(proxyTypeBuilder, targetType) && targetField.IsPublic) { // In case is public is pretty simple il.Emit(targetField.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, targetField); } else if (targetField.DeclaringType is not null && proxyTypeBuilder is not null) { // If the instance or the field are non public we need to create a Dynamic method to overpass the visibility checks // we can't access non public types so we have to cast to object type (in the instance object and the return type if is needed). string dynMethodName = $"_getNonPublicField_{targetField.DeclaringType.Name}_{targetField.Name}"; returnType = UseDirectAccessTo(proxyTypeBuilder, targetField.FieldType) ? targetField.FieldType : typeof(object); // We create the dynamic method Type[] dynParameters = targetField.IsStatic ? Type.EmptyTypes : new[] { typeof(object) }; DynamicMethod dynMethod = new DynamicMethod(dynMethodName, returnType, dynParameters, proxyTypeBuilder.Module, true); // Emit the dynamic method body LazyILGenerator dynIL = new LazyILGenerator(dynMethod.GetILGenerator()); if (!targetField.IsStatic) { // Emit the instance load in the dynamic method dynIL.Emit(OpCodes.Ldarg_0); if (targetField.DeclaringType != typeof(object)) { dynIL.Emit(targetField.DeclaringType !.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, targetField.DeclaringType); } } // Emit the field and convert before returning (in case of boxing) dynIL.Emit(targetField.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, targetField); dynIL.WriteTypeConversion(targetField.FieldType, returnType); dynIL.Emit(OpCodes.Ret); dynIL.Flush(); // Emit the call to the dynamic method il.WriteDynamicMethodCall(dynMethod, proxyTypeBuilder); }
private static MethodBuilder?GetPropertyGetMethod( TypeBuilder?proxyTypeBuilder, Type targetType, MemberInfo proxyMember, PropertyInfo targetProperty, FieldInfo?instanceField, Func <LazyILGenerator, Type, Type, Type> duckCastInnerToOuterFunc, Func <Type, Type, bool> needsDuckChaining) { MethodInfo?targetMethod = targetProperty.GetMethod; if (targetMethod is null) { return(null); } string proxyMemberName = proxyMember.Name; Type proxyMemberReturnType = typeof(object); Type[] proxyParameterTypes = Type.EmptyTypes; Type[] targetParametersTypes = GetPropertyGetParametersTypes(proxyTypeBuilder, targetProperty, true).ToArray(); if (proxyMember is PropertyInfo proxyProperty) { proxyMemberReturnType = proxyProperty.PropertyType; proxyParameterTypes = GetPropertyGetParametersTypes(proxyTypeBuilder, proxyProperty, true).ToArray(); if (proxyParameterTypes.Length != targetParametersTypes.Length) { DuckTypePropertyArgumentsLengthException.Throw(proxyProperty); } } else if (proxyMember is FieldInfo proxyField) { proxyMemberReturnType = proxyField.FieldType; proxyParameterTypes = Type.EmptyTypes; if (proxyParameterTypes.Length != targetParametersTypes.Length) { DuckTypePropertyArgumentsLengthException.Throw(targetProperty); } } MethodBuilder?proxyMethod = proxyTypeBuilder?.DefineMethod( "get_" + proxyMemberName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.Virtual, proxyMemberReturnType, proxyParameterTypes); LazyILGenerator il = new LazyILGenerator(proxyMethod?.GetILGenerator()); Type returnType = targetProperty.PropertyType; // Load the instance if needed if (!targetMethod.IsStatic) { il.Emit(OpCodes.Ldarg_0); if (instanceField is not null) { il.Emit(instanceField.FieldType.IsValueType ? OpCodes.Ldflda : OpCodes.Ldfld, instanceField); } } // Load the indexer keys to the stack for (int pIndex = 0; pIndex < proxyParameterTypes.Length; pIndex++) { Type proxyParamType = proxyParameterTypes[pIndex]; Type targetParamType = targetParametersTypes[pIndex]; // Check if the type can be converted of if we need to enable duck chaining if (NeedsDuckChaining(targetParamType, proxyParamType)) { // Load the argument and cast it as Duck type il.WriteLoadArgument(pIndex, false); il.Emit(OpCodes.Castclass, typeof(IDuckType)); // Call IDuckType.Instance property to get the actual value il.EmitCall(OpCodes.Callvirt, DuckTypeInstancePropertyInfo.GetMethod !, null !); targetParamType = typeof(object); } else { il.WriteLoadArgument(pIndex, false); } // If the target parameter type is public or if it's by ref we have to actually use the original target type. targetParamType = UseDirectAccessTo(proxyTypeBuilder, targetParamType) || targetParamType.IsByRef ? targetParamType : typeof(object); il.WriteTypeConversion(proxyParamType, targetParamType); targetParametersTypes[pIndex] = targetParamType; } // Call the getter method if (UseDirectAccessTo(proxyTypeBuilder, targetType)) { // If the instance is public we can emit directly without any dynamic method // Method call if (targetMethod.IsPublic) { // We can emit a normal call if we have a public instance with a public property method. il.EmitCall(targetMethod.IsStatic || (instanceField?.FieldType.IsValueType ?? false) ? OpCodes.Call : OpCodes.Callvirt, targetMethod, null !); } else { // In case we have a public instance and a non public property method we can use [Calli] with the function pointer il.WriteMethodCalli(targetMethod); } } else if (targetProperty.DeclaringType is not null && proxyTypeBuilder is not null && instanceField is not null) { // If the instance is not public we need to create a Dynamic method to overpass the visibility checks // we can't access non public types so we have to cast to object type (in the instance object and the return type). string dynMethodName = $"_getNonPublicProperty_{targetProperty.DeclaringType.Name}_{targetProperty.Name}"; returnType = UseDirectAccessTo(proxyTypeBuilder, targetProperty.PropertyType) ? targetProperty.PropertyType : typeof(object); // We create the dynamic method Type[] targetParameters = GetPropertyGetParametersTypes(proxyTypeBuilder, targetProperty, false, !targetMethod.IsStatic).ToArray(); Type[] dynParameters = targetMethod.IsStatic ? targetParametersTypes : (new[] { typeof(object) }).Concat(targetParametersTypes).ToArray(); DynamicMethod dynMethod = new DynamicMethod(dynMethodName, returnType, dynParameters, proxyTypeBuilder.Module, true); // Emit the dynamic method body LazyILGenerator dynIL = new LazyILGenerator(dynMethod.GetILGenerator()); if (!targetMethod.IsStatic) { dynIL.LoadInstanceArgument(typeof(object), targetProperty.DeclaringType); } for (int idx = targetMethod.IsStatic ? 0 : 1; idx < dynParameters.Length; idx++) { dynIL.WriteLoadArgument(idx, true); dynIL.WriteTypeConversion(dynParameters[idx], targetParameters[idx]); } dynIL.EmitCall(targetMethod.IsStatic || instanceField.FieldType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, targetMethod, null !); dynIL.WriteTypeConversion(targetProperty.PropertyType, returnType); dynIL.Emit(OpCodes.Ret); dynIL.Flush(); // Emit the call to the dynamic method il.WriteDynamicMethodCall(dynMethod, proxyTypeBuilder); }