Fixed Issue 651.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System.Runtime.InteropServices;
16 using OpenHardwareMonitor.Collections;
18 namespace OpenHardwareMonitor.Hardware {
20 internal static class PInvokeDelegateFactory {
22 private static readonly ModuleBuilder moduleBuilder =
23 AppDomain.CurrentDomain.DefineDynamicAssembly(
24 new AssemblyName("PInvokeDelegateFactoryInternalAssembly"),
25 AssemblyBuilderAccess.Run).DefineDynamicModule(
26 "PInvokeDelegateFactoryInternalModule");
28 private static readonly IDictionary<Pair<DllImportAttribute, Type>, Type> wrapperTypes =
29 new Dictionary<Pair<DllImportAttribute, Type>, Type>();
31 public static void CreateDelegate<T>(DllImportAttribute dllImportAttribute,
32 out T newDelegate) where T : class
35 Pair<DllImportAttribute, Type> key =
36 new Pair<DllImportAttribute, Type>(dllImportAttribute, typeof(T));
37 wrapperTypes.TryGetValue(key, out wrapperType);
39 if (wrapperType == null) {
40 wrapperType = CreateWrapperType(typeof(T), dllImportAttribute);
41 wrapperTypes.Add(key, wrapperType);
44 newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType,
45 dllImportAttribute.EntryPoint) as T;
49 private static Type CreateWrapperType(Type delegateType,
50 DllImportAttribute dllImportAttribute) {
52 TypeBuilder typeBuilder = moduleBuilder.DefineType(
53 "PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
55 MethodInfo methodInfo = delegateType.GetMethod("Invoke");
57 ParameterInfo[] parameterInfos = methodInfo.GetParameters();
58 int parameterCount = parameterInfos.GetLength(0);
60 Type[] parameterTypes = new Type[parameterCount];
61 for (int i = 0; i < parameterCount; i++)
62 parameterTypes[i] = parameterInfos[i].ParameterType;
64 MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod(
65 dllImportAttribute.EntryPoint, dllImportAttribute.Value,
66 MethodAttributes.Public | MethodAttributes.Static |
67 MethodAttributes.PinvokeImpl, CallingConventions.Standard,
68 methodInfo.ReturnType, parameterTypes,
69 dllImportAttribute.CallingConvention,
70 dllImportAttribute.CharSet);
72 foreach (ParameterInfo parameterInfo in parameterInfos)
73 methodBuilder.DefineParameter(parameterInfo.Position + 1,
74 parameterInfo.Attributes, parameterInfo.Name);
76 if (dllImportAttribute.PreserveSig)
77 methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
79 return typeBuilder.CreateType();