/// <summary> /// Get the managed size of a given type. This matches an IL-level sizeof(t), even if it cannot be determined normally in C#. /// Note that sizeof(t) != Marshal.SizeOf(t), f.e. when t is char. /// </summary> /// <param name="t">The type to get the size from.</param> /// <returns>The managed type size.</returns> public static int GetManagedSize(this Type t) { if (_GetManagedSizeCache.TryGetValue(t, out int size)) return size; if (_GetManagedSizeHelper == null) { Assembly asm; const string @namespace = "MonoMod.Utils"; const string @name = "GetManagedSizeHelper"; const string @fullName = @namespace + "." + @name; #if !CECIL0_9 using ( #endif ModuleDefinition module = ModuleDefinition.CreateModule( @fullName, new ModuleParameters() { Kind = ModuleKind.Dll, #if !CECIL0_9 && MONOMOD_UTILS ReflectionImporterProvider = MMReflectionImporter.Provider #endif } ) #if CECIL0_9 ; #else ) #endif { TypeDefinition type = new TypeDefinition( @namespace, @name, MC.TypeAttributes.Public | MC.TypeAttributes.Abstract | MC.TypeAttributes.Sealed ) { BaseType = module.TypeSystem.Object }; module.Types.Add(type); MethodDefinition method = new MethodDefinition(@name, MC.MethodAttributes.Public | MC.MethodAttributes.Static | MC.MethodAttributes.HideBySig, module.TypeSystem.Int32 ); GenericParameter genParam = new GenericParameter("T", method); method.GenericParameters.Add(genParam); type.Methods.Add(method); ILProcessor il = method.Body.GetILProcessor(); il.Emit(OpCodes.Sizeof, genParam); il.Emit(OpCodes.Ret); asm = ReflectionHelper.Load(module); } _GetManagedSizeHelper = asm.GetType(@fullName).GetMethod(@name); } size = (_GetManagedSizeHelper.MakeGenericMethod(t).CreateDelegate<Func<int>>() as Func<int>)(); lock (_GetManagedSizeCache) { return _GetManagedSizeCache[t] = size; } }
public MethodInfo Generate(object context) { string typeName = Environment.GetEnvironmentVariable("MONOMOD_DMD_TYPE"); switch (typeName?.ToLowerInvariant()) { case "dynamicmethod": case "dm": return(DMDEmitDynamicMethodGenerator.Generate(this, context)); #if !NETSTANDARD case "methodbuilder": case "mb": return(DMDEmitMethodBuilderGenerator.Generate(this, context)); #endif case "cecil": case "md": return(DMDCecilGenerator.Generate(this, context)); default: Type type = ReflectionHelper.GetType(typeName); if (type != null) { if (!t__IDMDGenerator.IsCompatible(type)) { throw new ArgumentException($"Invalid DMDGenerator type: {typeName}"); } if (!_DMDGeneratorCache.TryGetValue(typeName, out _IDMDGenerator gen)) { _DMDGeneratorCache[typeName] = gen = Activator.CreateInstance(type) as _IDMDGenerator; } return(gen.Generate(this, context)); } if (_PreferCecil) { return(DMDCecilGenerator.Generate(this, context)); } if (Debug) #if NETSTANDARD { return(DMDCecilGenerator.Generate(this, context)); } #else { return(DMDEmitMethodBuilderGenerator.Generate(this, context)); } #endif // In .NET Framework, DynamicILGenerator doesn't support fault and filter blocks. // This is a non-issue in .NET Core, yet it could still be an issue in mono. // https://github.com/dotnet/coreclr/issues/1764 #if NETFRAMEWORK if (Definition.Body.ExceptionHandlers.Any(eh => eh.HandlerType == ExceptionHandlerType.Fault || eh.HandlerType == ExceptionHandlerType.Filter )) #if NETSTANDARD { return(DMDCecilGenerator.Generate(this, context)); } #else { return(DMDEmitMethodBuilderGenerator.Generate(this, context)); } #endif #endif return(DMDEmitDynamicMethodGenerator.Generate(this, context)); } }