InjectHelper.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. using Mono.Cecil;
  2. using Mono.Cecil.Cil;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using UnityEngine;
  8. using UnityEditorInternal;
  9. using UnityEditor;
  10. using UnityEditor.Compilation;
  11. using UnityEngine.Assertions;
  12. using System.Text;
  13. namespace com.bbbirder.injection.editor
  14. {
  15. public static class InjectHelper
  16. {
  17. /// <summary>
  18. /// inject target assembly
  19. /// </summary>
  20. /// <param name="injections"></param>
  21. /// <param name="inputAssemblyPath"></param>
  22. /// <param name="outputAssemblyPath"></param>
  23. /// <returns>is written</returns>
  24. internal static bool InjectAssembly(InjectionInfo[] injections, string inputAssemblyPath, string outputAssemblyPath, bool isEditor, BuildTarget buildTarget)
  25. {
  26. // set up assembly resolver
  27. var resolver = new DefaultAssemblyResolver();
  28. var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup);
  29. var assemblySearchFolders = UnityInjectUtils.GetAssemblySearchFolders(isEditor, buildTarget);
  30. var systemAssemblyDirectories = CompilationPipeline.GetSystemAssemblyDirectories(apiCompatibilityLevel);
  31. resolver.AddSearchDirectory(Path.GetDirectoryName(outputAssemblyPath));
  32. foreach (var folder in assemblySearchFolders)
  33. {
  34. resolver.AddSearchDirectory(folder);
  35. }
  36. foreach (var folder in systemAssemblyDirectories)
  37. {
  38. resolver.AddSearchDirectory(folder);
  39. }
  40. var IsPlayerAssembly = Path.GetFullPath(inputAssemblyPath).StartsWith(Path.GetFullPath("Library/"))
  41. || Path.GetFullPath(inputAssemblyPath).StartsWith(Path.GetFullPath("Temp/"));
  42. var targetAssembly = AssemblyDefinition.ReadAssembly(inputAssemblyPath, new ReaderParameters()
  43. {
  44. AssemblyResolver = resolver,
  45. ReadingMode = ReadingMode.Immediate,
  46. ReadSymbols = IsPlayerAssembly,
  47. InMemory = true,
  48. });
  49. foreach(var inj in injections)
  50. {
  51. var providerMethod = inj.DryInjectMethod;
  52. if (providerMethod is null) continue;
  53. var methodName = inj.DryInjectMethodName;
  54. var targetType = GetCorrespondingType(targetAssembly.MainModule, inj.DryInjectAssmemble);
  55. if (targetType == null)
  56. {
  57. throw new($"Cannot find Type `{inj.DryInjectAssmemble}` in target assembly {inputAssemblyPath}");
  58. }
  59. var providerAssemblyPath = providerMethod.DeclaringType.Assembly.GetAssemblyPath();
  60. var providerAssembly = AssemblyDefinition.ReadAssembly(providerAssemblyPath, new ReaderParameters()
  61. {
  62. AssemblyResolver = resolver,
  63. ReadingMode = ReadingMode.Immediate,
  64. ReadSymbols = IsPlayerAssembly,
  65. InMemory = true,
  66. });
  67. var providerType = GetCorrespondingType(providerAssembly.MainModule, providerMethod.DeclaringType);
  68. var targetMethod = providerType.FindMethod(providerMethod.GetSignature()).Resolve();
  69. if (targetMethod is null)
  70. {
  71. throw new($"Cannot find Method `{methodName}` in Type `{providerMethod.DeclaringType}`");
  72. }
  73. //add field
  74. targetType.AddInjectField(targetMethod, methodName, true);
  75. }
  76. /*
  77. //mark check
  78. var injected = targetAssembly.MainModule.Types.Any(t =>
  79. Constants.INJECTED_MARK_NAME == t.Name &&
  80. Constants.INJECTED_MARK_NAMESPACE == t.Namespace);
  81. if (injected)
  82. {
  83. targetAssembly.Release();
  84. return false;
  85. }
  86. */
  87. foreach (var group in injections.GroupBy(inj => inj.InjectedMethod))
  88. {
  89. var injectedMethod = group.Key;
  90. if (injectedMethod is null) continue;
  91. var type = injectedMethod.DeclaringType;
  92. var methodName = injectedMethod.Name;
  93. var targetType = GetCorrespondingType(targetAssembly.MainModule, type);
  94. if (targetType is null)
  95. {
  96. throw new($"Cannot find Type `{type}` in target assembly {inputAssemblyPath}");
  97. }
  98. var targetMethod = targetType.FindMethod(injectedMethod.GetSignature()).Resolve();
  99. if (targetMethod is null)
  100. {
  101. throw new($"Cannot find Method `{methodName}` in Type `{type}`");
  102. }
  103. //add origin
  104. var originalMethod = targetType.DuplicateOriginalMethod(targetMethod);
  105. //add field
  106. var injectionName = Constants.GetInjectedFieldName(methodName, targetMethod.GetSignature());
  107. var (field, fieldInvoke) = targetType.AddInjectField(targetMethod, injectionName);
  108. //add method
  109. targetType.AddInjectionMethod(targetMethod, originalMethod, field, fieldInvoke, methodName);
  110. }
  111. //mark make
  112. var InjectedMark = new TypeDefinition(
  113. Constants.INJECTED_MARK_NAMESPACE,
  114. Constants.INJECTED_MARK_NAME,
  115. TypeAttributes.Class,
  116. targetAssembly.MainModule.TypeSystem.Object);
  117. targetAssembly.MainModule.Types.Add(InjectedMark);
  118. targetAssembly.Write(outputAssemblyPath, new WriterParameters()
  119. {
  120. WriteSymbols = IsPlayerAssembly,
  121. });
  122. targetAssembly.Release();
  123. return true;
  124. static TypeDefinition GetCorrespondingType(ModuleDefinition module, Type t1)
  125. {
  126. var typeDefinition = default(TypeDefinition);
  127. foreach (var type in GetContainingTypes(t1).Reverse())
  128. {
  129. if (typeDefinition is null)
  130. {
  131. typeDefinition = module.Types.FirstOrDefault(t => type.FullName == t.FullName);
  132. }
  133. else
  134. {
  135. typeDefinition = typeDefinition.NestedTypes.FirstOrDefault(t => t.Name == type.Name);
  136. }
  137. if (typeDefinition is null) return null;
  138. }
  139. return typeDefinition;
  140. static IEnumerable<Type> GetContainingTypes(Type type)
  141. {
  142. while (type != null)
  143. {
  144. yield return type;
  145. type = type.DeclaringType;
  146. }
  147. }
  148. }
  149. }
  150. static MethodDefinition DuplicateOriginalMethod(this TypeDefinition targetType, MethodDefinition targetMethod)
  151. {
  152. var originName = Constants.GetOriginMethodName(targetMethod.Name, targetMethod.GetSignature());
  153. var duplicatedMethod = targetType.Methods.FirstOrDefault(m => m.Name == originName);
  154. if (duplicatedMethod is null)
  155. {
  156. duplicatedMethod = targetMethod.Clone();
  157. duplicatedMethod.IsPrivate = true;
  158. duplicatedMethod.Name = originName;
  159. targetType.Methods.Add(duplicatedMethod);
  160. }
  161. return duplicatedMethod;
  162. }
  163. static void Release(this AssemblyDefinition assemblyDefinition)
  164. {
  165. if (assemblyDefinition == null) return;
  166. assemblyDefinition.MainModule.AssemblyResolver?.Dispose();
  167. assemblyDefinition.MainModule.SymbolReader?.Dispose();
  168. assemblyDefinition.Dispose();
  169. }
  170. static (FieldDefinition field, MethodReference fieldInvokeMethod) AddInjectField(this TypeDefinition targetType, MethodDefinition targetMethod, string injectionName, bool isPublic=false)
  171. {
  172. var HasThis = targetMethod.HasThis;
  173. var Parameters = targetMethod.Parameters;
  174. var GenericParameters = targetMethod.GenericParameters;
  175. // var CustomAttributes = targetMethod.CustomAttributes;
  176. var ReturnType = targetMethod.ReturnType;
  177. var ReturnVoid = targetMethod.IsReturnVoid();
  178. //define delegate
  179. // var delegateParameters = new List<TypeReference>();
  180. // if(HasThis) delegateParameters.Add(targetType);
  181. // foreach(var p in Parameters) delegateParameters.Add(p.ParameterType);
  182. // var delegateType = targetType.Module.CreateDelegateType(Settings.GetDelegateTypeName(methodName),targetType,ReturnType,delegateParameters);
  183. // targetType.NestedTypes.Add(delegateType);
  184. var genName = targetMethod.IsReturnVoid() ? "System.Action" : "System.Func";
  185. var genPCnt = Parameters.Count;
  186. if (!ReturnVoid) genPCnt++;
  187. if (HasThis) genPCnt++;
  188. if (genPCnt > 0)
  189. {
  190. genName += "`" + genPCnt;
  191. }
  192. var rawGenType = targetType.Module.FindType(Type.GetType(genName));
  193. var genType = targetType.Module.ImportReference(rawGenType);
  194. var genInst = new GenericInstanceType(genType);
  195. if (HasThis)
  196. genInst.GenericArguments.Add(targetType);
  197. foreach (var p in Parameters)
  198. genInst.GenericArguments.Add(p.ParameterType);
  199. if (!ReturnVoid)
  200. genInst.GenericArguments.Add(ReturnType);
  201. //store fields
  202. var sfldInject = targetType.Fields.FirstOrDefault(f => f.Name == injectionName);
  203. if (sfldInject is null)
  204. {
  205. sfldInject = new FieldDefinition(injectionName,
  206. FieldAttributes.Static | (isPublic ? FieldAttributes.Public : FieldAttributes.Private),
  207. genInst);
  208. targetType.Fields.Add(sfldInject);
  209. }
  210. // var sfldOrigin = new FieldDefinition(originName,
  211. // FieldAttributes.Private|FieldAttributes.Static|FieldAttributes.Assembly,
  212. // targetType.Module.ImportReference(typeof(Delegate)));
  213. // var resMth = genInst.Resolve();
  214. var genMtd = rawGenType.FindMethodByName("Invoke");
  215. // genMtd.DeclaringType = genInst;
  216. var mnlMth = new MethodReference(genMtd.Name, genMtd.ReturnType, genInst)
  217. {
  218. ExplicitThis = false,
  219. HasThis = true,
  220. CallingConvention = genMtd.CallingConvention
  221. };
  222. foreach (var p in genMtd.Parameters)
  223. mnlMth.Parameters.Add(p);
  224. return (sfldInject, mnlMth);
  225. }
  226. static void AddInjectionMethod(
  227. this TypeDefinition targetType,
  228. MethodDefinition targetMethod, MethodDefinition originalMethod,
  229. FieldDefinition delegateField, MethodReference fieldInvoke, string methodName
  230. )
  231. {
  232. var argidx = 0;
  233. var HasThis = targetMethod.HasThis;
  234. var Parameters = targetMethod.Parameters;
  235. // var GenericParameters = targetMethod.GenericParameters;
  236. // var CustomAttributes = targetMethod.CustomAttributes;
  237. var ReturnType = targetMethod.ReturnType;
  238. //redirect method
  239. if (!targetMethod.HasBody)
  240. {
  241. throw new ArgumentException($"method {targetMethod.Name} in type {targetType.Name} dont have a body");
  242. }
  243. targetMethod.Body.Instructions.Clear();
  244. var delegateType = delegateField.FieldType.Resolve();
  245. var ilProcessor = targetMethod.Body.GetILProcessor();
  246. var tagOp = Instruction.Create(OpCodes.Nop);
  247. //check null
  248. ilProcessor.Append(Instruction.Create(OpCodes.Ldsfld, delegateField));
  249. ilProcessor.Append(Instruction.Create(OpCodes.Brtrue_S, tagOp));
  250. // //set field
  251. // if(HasThis)
  252. // ilProcessor.Append(Instruction.Create(OpCodes.Ldarg_0));
  253. // else
  254. // ilProcessor.Append(Instruction.Create(OpCodes.Ldnull));
  255. // ilProcessor.Append(Instruction.Create(OpCodes.Ldftn, originalMethod));
  256. // ilProcessor.Append(Instruction.Create(OpCodes.Newobj,delegateType.FindMethod(".ctor")));
  257. // ilProcessor.Append(Instruction.Create(OpCodes.Stsfld,delegateField));
  258. //invoke origin
  259. argidx = 0;
  260. if (HasThis)
  261. ilProcessor.Append(ilProcessor.createLdarg(argidx++));
  262. for (var i = 0; i < Parameters.Count; i++)
  263. {
  264. var pType = Parameters[i].ParameterType;
  265. ilProcessor.Append(ilProcessor.createLdarg(argidx++));
  266. // if(pType.IsValueType)
  267. // ilProcessor.Append(Instruction.Create(OpCodes.Box,pType));
  268. }
  269. if (HasThis)
  270. ilProcessor.Append(Instruction.Create(OpCodes.Callvirt, originalMethod));
  271. else
  272. ilProcessor.Append(Instruction.Create(OpCodes.Call, originalMethod));
  273. // if(originalMethod.IsReturnVoid())
  274. // ilProcessor.Append(Instruction.Create(OpCodes.Pop));
  275. ilProcessor.Append(Instruction.Create(OpCodes.Ret));
  276. //invoke
  277. ilProcessor.Append(tagOp);
  278. ilProcessor.Append(Instruction.Create(OpCodes.Ldsfld, delegateField));
  279. argidx = 0;
  280. if (HasThis)
  281. ilProcessor.Append(ilProcessor.createLdarg(argidx++));
  282. for (var i = 0; i < Parameters.Count; i++)
  283. {
  284. var pType = Parameters[i].ParameterType;
  285. ilProcessor.Append(ilProcessor.createLdarg(argidx++));
  286. // if(pType.IsValueType)
  287. // ilProcessor.Append(Instruction.Create(OpCodes.Box,pType));
  288. }
  289. ilProcessor.Append(Instruction.Create(OpCodes.Callvirt,
  290. (fieldInvoke)));
  291. // Fixes: conditional boxing here is unnecessary
  292. // if(ReturnType.IsComplexValueType())
  293. // ilProcessor.Append(Instruction.Create(OpCodes.Box,ReturnType));
  294. ilProcessor.Append(Instruction.Create(OpCodes.Nop));
  295. ilProcessor.Append(Instruction.Create(OpCodes.Ret));
  296. }
  297. static Instruction createLdarg(this ILProcessor ilProcessor, int i)
  298. {
  299. if (i < s_ldargs.Length)
  300. {
  301. return Instruction.Create(s_ldargs[i]);
  302. }
  303. else if (i < 256)
  304. {
  305. return ilProcessor.Create(OpCodes.Ldarg_S, (byte)i);
  306. }
  307. else
  308. {
  309. return ilProcessor.Create(OpCodes.Ldarg, (short)i);
  310. }
  311. }
  312. /// <summary>
  313. /// Create a clone of the given method definition
  314. /// </summary>
  315. public static MethodDefinition Clone(this MethodDefinition source)
  316. {
  317. var result = new MethodDefinition(source.Name, source.Attributes, source.ReturnType)
  318. {
  319. ImplAttributes = source.ImplAttributes,
  320. SemanticsAttributes = source.SemanticsAttributes,
  321. HasThis = source.HasThis,
  322. ExplicitThis = source.ExplicitThis,
  323. CallingConvention = source.CallingConvention
  324. };
  325. foreach (var p in source.Parameters) result.Parameters.Add(p);
  326. // foreach (var p in source.CustomAttributes) result.CustomAttributes.Add(p);
  327. foreach (var p in source.GenericParameters) result.GenericParameters.Add(p);
  328. if (source.HasBody)
  329. {
  330. result.Body = source.Body.Clone(result);
  331. }
  332. return result;
  333. }
  334. /// <summary>
  335. /// Create a clone of the given method body
  336. /// </summary>
  337. public static MethodBody Clone(this MethodBody source, MethodDefinition target)
  338. {
  339. var result = new MethodBody(target) { InitLocals = source.InitLocals, MaxStackSize = source.MaxStackSize };
  340. var worker = result.GetILProcessor();
  341. if (source.HasVariables)
  342. {
  343. foreach (var v in source.Variables)
  344. {
  345. result.Variables.Add(v);
  346. }
  347. }
  348. foreach (var i in source.Instructions)
  349. {
  350. // Poor mans clone, but sufficient for our needs
  351. var clone = Instruction.Create(OpCodes.Nop);
  352. clone.OpCode = i.OpCode;
  353. clone.Operand = i.Operand;
  354. worker.Append(clone);
  355. }
  356. return result;
  357. }
  358. internal static bool IsReturnVoid(this MethodDefinition md)
  359. => md.ReturnType.ToString() == voidType.ToString();
  360. internal static bool IsReturnValueType(this MethodDefinition md)
  361. => !md.IsReturnVoid() && md.ReturnType.IsValueType;
  362. internal static bool IsComplexValueType(this TypeReference td)
  363. => td.ToString() != voidType.ToString() && !td.IsPrimitive;
  364. internal static Type GetUnderlyingType(this TypeReference td)
  365. => td.IsPrimitive ? Type.GetType(td.Name) : objType;
  366. internal static string GetSignature(this MethodDefinition md)
  367. {
  368. var builder = new StringBuilder();
  369. builder.Append(md.Name);
  370. if (md.HasGenericParameters)
  371. {
  372. builder.Append('`');
  373. builder.Append(md.GenericParameters.Count);
  374. }
  375. builder.Append('(');
  376. if (md.HasParameters)
  377. {
  378. var parameters = md.Parameters;
  379. for (int i = 0; i < parameters.Count; i++)
  380. {
  381. ParameterDefinition parameterDefinition = parameters[i];
  382. if (i > 0)
  383. {
  384. builder.Append(",");
  385. }
  386. AppendTypeFullName(builder, parameterDefinition.ParameterType);
  387. }
  388. }
  389. builder.Append(')');
  390. return builder.ToString();
  391. static void AppendTypeFullName(StringBuilder builder, TypeReference type)
  392. {
  393. if (!string.IsNullOrEmpty(type.Namespace))
  394. {
  395. builder.Append(type.Namespace);
  396. builder.Append("::");
  397. }
  398. var stack = new Stack<TypeReference>();
  399. var declaringType = type;
  400. while (null != declaringType)
  401. {
  402. stack.Push(declaringType);
  403. declaringType = declaringType.DeclaringType;
  404. }
  405. while (stack.TryPop(out var nestedType)) AppendNestedType(builder, nestedType);
  406. }
  407. static void AppendNestedType(StringBuilder builder, TypeReference type)
  408. {
  409. builder.Append(type.Name);
  410. if (type is GenericInstanceType gInst)
  411. {
  412. builder.Append('<');
  413. var args = gInst.GenericArguments;
  414. for (int i = 0; i < args.Count; i++)
  415. {
  416. if (i != 0)
  417. {
  418. builder.Append(',');
  419. }
  420. AppendTypeFullName(builder, args[i]);
  421. }
  422. builder.Append('>');
  423. }
  424. }
  425. }
  426. internal static MethodReference FindMethod(this TypeDefinition td, string methodSignature)
  427. {
  428. var method = td.Methods.FirstOrDefault(m => m.GetSignature().Equals(methodSignature));
  429. if (method is null) return null;
  430. return td.Module.ImportReference(method);
  431. }
  432. internal static MethodReference FindMethodByName(this TypeDefinition td, string methodName)
  433. => td.Module.ImportReference(td.Methods.FirstOrDefault(m => m.Name.Equals(methodName)));
  434. internal static TypeDefinition FindType(this ModuleDefinition md, Type type)
  435. {
  436. DebugHelper.IsNotNull(type);
  437. HashSet<string> knownAssemblyNames = new();
  438. List<ModuleDefinition> modules = new();
  439. GetModules(md);
  440. foreach (var m in modules)
  441. {
  442. DebugHelper.IsNotNull(m);
  443. var tp = m.GetType(type.Namespace, type.Name);
  444. if (null != tp)
  445. {
  446. return tp;
  447. }
  448. }
  449. return null;
  450. void GetModules(ModuleDefinition md)
  451. {
  452. if (knownAssemblyNames.Contains(md.FileName))
  453. return;
  454. var refModules = md.AssemblyReferences
  455. .Select(an =>
  456. {
  457. try
  458. {
  459. return md.AssemblyResolver.Resolve(an).MainModule;
  460. }
  461. catch
  462. {
  463. return null;
  464. }
  465. })
  466. .Where(r => r != null)
  467. .ToArray();
  468. AddModule(md);
  469. foreach (var m in refModules)
  470. {
  471. GetModules(m);
  472. }
  473. }
  474. void AddModule(ModuleDefinition md)
  475. {
  476. var fileName = md.FileName;
  477. if (!knownAssemblyNames.Contains(fileName))
  478. modules.Add(md);
  479. knownAssemblyNames.Add(fileName);
  480. }
  481. // return new TypeReference(type.Namespace,type.Name,md,md.TypeSystem.CoreLibrary);
  482. }
  483. internal static TypeReference FindType<T>(this ModuleDefinition md)
  484. {
  485. return FindType(md, typeof(T));
  486. // return new TypeReference(typeof(T).Namespace,typeof(T).Name,md,md.TypeSystem.CoreLibrary);
  487. }
  488. internal static TypeDefinition CreateDelegateType(this ModuleDefinition assembly, string name, TypeDefinition declaringType,
  489. TypeReference returnType, IEnumerable<TypeReference> parameters)
  490. {
  491. var voidType = assembly.TypeSystem.Void;
  492. var objectType = assembly.TypeSystem.Object;
  493. var nativeIntType = assembly.TypeSystem.IntPtr;
  494. var asyncResultType = assembly.FindType<IAsyncResult>();
  495. var asyncCallbackType = assembly.FindType<AsyncCallback>();
  496. var multicastDelegateType = assembly.FindType<MulticastDelegate>();
  497. var DelegateTypeAttributes = TypeAttributes.NestedPublic | TypeAttributes.Sealed;
  498. var dt = new TypeDefinition("", name, DelegateTypeAttributes, multicastDelegateType);
  499. dt.DeclaringType = declaringType;
  500. // add constructor
  501. var ConstructorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
  502. var constructor = new MethodDefinition(".ctor", ConstructorAttributes, voidType);
  503. constructor.Parameters.Add(new ParameterDefinition("objectInstance", ParameterAttributes.None, objectType));
  504. constructor.Parameters.Add(new ParameterDefinition("functionPtr", ParameterAttributes.None, nativeIntType));
  505. constructor.ImplAttributes = MethodImplAttributes.Runtime;
  506. dt.Methods.Add(constructor);
  507. // add BeginInvoke
  508. var DelegateMethodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.VtableLayoutMask;
  509. var beginInvoke = new MethodDefinition("BeginInvoke", DelegateMethodAttributes, asyncResultType);
  510. foreach (var p in parameters)
  511. {
  512. beginInvoke.Parameters.Add(new ParameterDefinition(p));
  513. }
  514. beginInvoke.Parameters.Add(new ParameterDefinition("callback", ParameterAttributes.None, asyncCallbackType));
  515. beginInvoke.Parameters.Add(new ParameterDefinition("object", ParameterAttributes.None, objectType));
  516. beginInvoke.ImplAttributes = MethodImplAttributes.Runtime;
  517. dt.Methods.Add(beginInvoke);
  518. // add EndInvoke
  519. var endInvoke = new MethodDefinition("EndInvoke", DelegateMethodAttributes, returnType);
  520. endInvoke.Parameters.Add(new ParameterDefinition("result", ParameterAttributes.None, asyncResultType));
  521. endInvoke.ImplAttributes = MethodImplAttributes.Runtime;
  522. dt.Methods.Add(endInvoke);
  523. // add Invoke
  524. var invoke = new MethodDefinition("Invoke", DelegateMethodAttributes, returnType);
  525. foreach (var p in parameters)
  526. {
  527. // if(!p.IsValueType){
  528. // invoke.Parameters.Add(new ParameterDefinition(p.Name,ParameterAttributes.In,objectType));
  529. // }else{
  530. invoke.Parameters.Add(new ParameterDefinition(p));
  531. // }
  532. }
  533. invoke.ImplAttributes = MethodImplAttributes.Runtime;
  534. dt.Methods.Add(invoke);
  535. return dt;
  536. }
  537. static Type voidType = typeof(void);
  538. static Type objType = typeof(object);
  539. static OpCode[] s_ldargs = new[] { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3 };
  540. }
  541. }