Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Threading;
- namespace EmitMethodWithInParamTest
- {
- public struct StructParam
- {
- public String Data;
- }
- public interface ISomeInterface
- {
- Int32 SomeMethod(in StructParam param);
- }
- static class EmitExtension
- {
- public static void ReplicateCustomAttributes(this ParameterBuilder paramBuilder, ParameterInfo paramInfo)
- {
- foreach (var attrData in paramInfo.GetCustomAttributesData())
- {
- var ctorArgs = attrData.ConstructorArguments.Select(arg => arg.Value).ToArray();
- // Handling variable arguments
- var ctorParamInfos = attrData.Constructor.GetParameters();
- if (ctorParamInfos.Length > 0 &&
- ctorParamInfos.Last().IsDefined(typeof(ParamArrayAttribute)) &&
- ctorArgs.Last() is IReadOnlyCollection<CustomAttributeTypedArgument> variableArgs)
- {
- ctorArgs[ctorArgs.Length - 1] = variableArgs.Select(arg => arg.Value).ToArray();
- }
- var namedPropArgs = attrData.NamedArguments.Where(arg => !arg.IsField);
- var namedPropInfos = namedPropArgs.Select(arg => (PropertyInfo)arg.MemberInfo).ToArray();
- var namedPropValues = namedPropArgs.Select(arg => arg.TypedValue.Value).ToArray();
- var namedFieldArgs = attrData.NamedArguments.Where(arg => arg.IsField);
- var namedFieldInfos = namedPropArgs.Select(arg => (FieldInfo)arg.MemberInfo).ToArray();
- var namedFieldValues = namedPropArgs.Select(arg => arg.TypedValue.Value).ToArray();
- var attrBuilder = new CustomAttributeBuilder(attrData.Constructor,
- ctorArgs, namedPropInfos, namedPropValues, namedFieldInfos, namedFieldValues);
- paramBuilder.SetCustomAttribute(attrBuilder);
- }
- }
- }
- class Program
- {
- static Program()
- {
- Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-us");
- }
- static void Main(String[] args)
- {
- var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run);
- var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
- var typeBuilder = moduleBuilder.DefineType("SomeClass",
- TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout,
- null /*base class*/,
- new[] { typeof(ISomeInterface) });
- var methodInfoToImpl = typeof(ISomeInterface).GetMethod(nameof(ISomeInterface.SomeMethod));
- var paramInfos = methodInfoToImpl.GetParameters();
- var methodBuilder = typeBuilder.DefineMethod(methodInfoToImpl.Name,
- MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final,
- CallingConventions.HasThis,
- methodInfoToImpl.ReturnType,
- paramInfos.Select(pi => pi.ParameterType).ToArray());
- foreach (var paramInfo in paramInfos)
- {
- // paramInfo.Position is zero-based but DefineParameter requires 1-based index.
- var paramBuilder = methodBuilder.DefineParameter(paramInfo.Position + 1, paramInfo.Attributes, paramInfo.Name);
- if (paramInfo.Attributes.HasFlag(ParameterAttributes.HasDefault))
- {
- paramBuilder.SetConstant(paramInfo.DefaultValue);
- }
- paramBuilder.ReplicateCustomAttributes(paramInfo);
- }
- // Dummy implementation for example. Always throws NotImplementedException.
- var ilGen = methodBuilder.GetILGenerator();
- ilGen.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(Type.EmptyTypes));
- ilGen.Emit(OpCodes.Throw);
- var builtType = typeBuilder.CreateType(); // <- TypeLoadException("Method 'SomeMethod' in type 'SomeClass' from assembly 'DynamicAssembly, ...' does not have an implementation.") is thrown.
- var generatedObj = (ISomeInterface)Activator.CreateInstance(builtType);
- var someParam = new StructParam() { Data = "SomeData" };
- var result = generatedObj.SomeMethod(in someParam); // <- NotImplementedException expected by dummy implementation if executed.
- Console.WriteLine($"Result: {result}");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement