Advertisement
Guest User

EmitMethodWithInParamTest.cs

a guest
Jun 12th, 2019
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.09 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. using System.Threading;
  8.  
  9. namespace EmitMethodWithInParamTest
  10. {
  11.     public struct StructParam
  12.     {
  13.         public String Data;
  14.     }
  15.  
  16.     public interface ISomeInterface
  17.     {
  18.         Int32 SomeMethod(in StructParam param);
  19.     }
  20.  
  21.     static class EmitExtension
  22.     {
  23.         public static void ReplicateCustomAttributes(this ParameterBuilder paramBuilder, ParameterInfo paramInfo)
  24.         {
  25.             foreach (var attrData in paramInfo.GetCustomAttributesData())
  26.             {
  27.                 var ctorArgs = attrData.ConstructorArguments.Select(arg => arg.Value).ToArray();
  28.  
  29.                 // Handling variable arguments
  30.                 var ctorParamInfos = attrData.Constructor.GetParameters();
  31.                 if (ctorParamInfos.Length > 0 &&
  32.                     ctorParamInfos.Last().IsDefined(typeof(ParamArrayAttribute)) &&
  33.                     ctorArgs.Last() is IReadOnlyCollection<CustomAttributeTypedArgument> variableArgs)
  34.                 {
  35.                     ctorArgs[ctorArgs.Length - 1] = variableArgs.Select(arg => arg.Value).ToArray();
  36.                 }
  37.  
  38.                 var namedPropArgs = attrData.NamedArguments.Where(arg => !arg.IsField);
  39.                 var namedPropInfos = namedPropArgs.Select(arg => (PropertyInfo)arg.MemberInfo).ToArray();
  40.                 var namedPropValues = namedPropArgs.Select(arg => arg.TypedValue.Value).ToArray();
  41.  
  42.                 var namedFieldArgs = attrData.NamedArguments.Where(arg => arg.IsField);
  43.                 var namedFieldInfos = namedPropArgs.Select(arg => (FieldInfo)arg.MemberInfo).ToArray();
  44.                 var namedFieldValues = namedPropArgs.Select(arg => arg.TypedValue.Value).ToArray();
  45.  
  46.                 var attrBuilder = new CustomAttributeBuilder(attrData.Constructor,
  47.                     ctorArgs, namedPropInfos, namedPropValues, namedFieldInfos, namedFieldValues);
  48.                 paramBuilder.SetCustomAttribute(attrBuilder);
  49.             }
  50.         }
  51.     }
  52.  
  53.     class Program
  54.     {
  55.         static Program()
  56.         {
  57.             Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-us");
  58.         }
  59.  
  60.         static void Main(String[] args)
  61.         {
  62.             var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run);
  63.             var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
  64.             var typeBuilder = moduleBuilder.DefineType("SomeClass",
  65.                 TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
  66.                 null /*base class*/,
  67.                 new[] { typeof(ISomeInterface) });
  68.  
  69.             var methodInfoToImpl = typeof(ISomeInterface).GetMethod(nameof(ISomeInterface.SomeMethod));
  70.             var paramInfos = methodInfoToImpl.GetParameters();
  71.  
  72.             var methodBuilder = typeBuilder.DefineMethod(methodInfoToImpl.Name,
  73.                 MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final,
  74.                 CallingConventions.HasThis,
  75.                 methodInfoToImpl.ReturnType,
  76.                 paramInfos.Select(pi => pi.ParameterType).ToArray());
  77.  
  78.             foreach (var paramInfo in paramInfos)
  79.             {
  80.                 // paramInfo.Position is zero-based but DefineParameter requires 1-based index.
  81.                 var paramBuilder = methodBuilder.DefineParameter(paramInfo.Position + 1, paramInfo.Attributes, paramInfo.Name);
  82.                 if (paramInfo.Attributes.HasFlag(ParameterAttributes.HasDefault))
  83.                 {
  84.                     paramBuilder.SetConstant(paramInfo.DefaultValue);
  85.                 }
  86.                 paramBuilder.ReplicateCustomAttributes(paramInfo);
  87.             }
  88.  
  89.             // Dummy implementation for example. Always throws NotImplementedException.
  90.             var ilGen = methodBuilder.GetILGenerator();
  91.             ilGen.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(Type.EmptyTypes));
  92.             ilGen.Emit(OpCodes.Throw);
  93.  
  94.             var builtType = typeBuilder.CreateType();               // <- TypeLoadException("Method 'SomeMethod' in type 'SomeClass' from assembly 'DynamicAssembly, ...' does not have an implementation.") is thrown.
  95.             var generatedObj = (ISomeInterface)Activator.CreateInstance(builtType);
  96.  
  97.             var someParam = new StructParam() { Data = "SomeData" };
  98.             var result = generatedObj.SomeMethod(in someParam);     // <- NotImplementedException expected by dummy implementation if executed.
  99.  
  100.             Console.WriteLine($"Result: {result}");
  101.         }
  102.     }
  103. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement