public void GetFilter() { MethodInfo[] list = InterfaceType.GetMethods(); foreach (MethodInfo l in list) { if (this.UserLowercase) { actionList.Add(l.Name.ToLower(), l); } else { actionList.Add(l.Name, l); } } }
internal void SaveMethod() { MethodWrapContext methodWrapContext; MethodInfo[] interfacemethods = InterfaceType.GetMethods(); MethodInfo interfacemethodInfo; MethodItem methodItem; for (int i = 0; i < interfacemethods.Length; i++) { interfacemethodInfo = interfacemethods[i]; methodWrapContext = MethodWrapContext.GetContext(this, interfacemethodInfo); methodItem = new MethodItem(interfacemethodInfo, methodWrapContext); MethodCache[interfacemethodInfo] = methodItem; } }
private void GenerateMethods() { var methodNames = new HashSet <string>(); var allMethods = new List <MethodInfo>(); foreach (MethodInfo method in InterfaceType .GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public) .Concat( InterfaceType.GetInterfaces() .SelectMany( x => x.GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public))) .OrderBy(x => x.Name)) { if (!methodNames.Add(method.Name)) { throw new ArgumentException( string.Format("The type contains at least two methods with the same name '{0}': This is not supported", method.Name)); } allMethods.Add(method); } foreach (var method in allMethods) { if (method.IsSpecialName) { var methodName = method.Name; if (methodName.StartsWith("add_")) { GenerateAddEvent(method); } else if (methodName.StartsWith("remove_")) { GenerateRemoveEvent(method); } else { GenerateMethodInvocation(method); } } else { GenerateMethodInvocation(method); } } }
public static void GenerateForAssembly(Assembly asm) { var types = asm.GetTypes() .Select(x => (type: x, attribute: x.GetCustomAttribute <NativeInterfaceAttribute>())) .Where(x => x.attribute is not null) .ToArray(); var typesActual = types.Select(x => x.attribute !.InterfaceType).ToArray(); var folderName = asm.GetName().Name !+"Files"; Directory.CreateDirectory(folderName); foreach (var t in types) { StringBuilder builder = new StringBuilder(); builder.AppendLine("using WPIUtil.ILGeneration;"); builder.AppendLine("using System.Runtime.CompilerServices;"); builder.AppendLine($"namespace {t.attribute!.InterfaceType.Namespace}"); builder.AppendLine("{"); builder.AppendLine($"public unsafe class {t.type.Name}Native : {t.attribute!.InterfaceType.Name}"); builder.AppendLine("{"); var methods = t.attribute !.InterfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance); List <string> inits = new List <string>(); foreach (var method in methods.Where(x => x.IsAbstract)) { var statusCheckRange = method.GetCustomAttribute <StatusCheckRangeAttribute>(); var statusCheckRet = method.GetCustomAttribute <StatusCheckReturnValueAttribute>(); var statusCheckLastParam = method.GetCustomAttribute <StatusCheckLastParameterAttribute>(); if (statusCheckRange != null) { GenerateStatusCheckRangeMethod(method, builder, statusCheckRange, inits); } else if (statusCheckRet != null) { GenerateStatusCheckReturnMethod(method, builder, inits); } else if (statusCheckLastParam != null) { GenerateStatusCheckLastParameterMethod(method, builder, inits); } else { GenerateNoStatusMethod(method, builder, inits); } builder.AppendLine(); builder.AppendLine(); } builder.AppendLine(); builder.AppendLine($"public {t.type.Name}Native(IFunctionPointerLoader loader)"); builder.AppendLine("{"); builder.AppendLine("if (loader == null)"); builder.AppendLine("{"); builder.AppendLine("throw new ArgumentNullException(nameof(loader));"); builder.AppendLine("}"); builder.AppendLine(); foreach (var method in inits) { builder.AppendLine(method); } builder.AppendLine("}"); builder.AppendLine(); builder.AppendLine("}"); builder.AppendLine("}"); File.WriteAllText(Path.Join(folderName, t.type.Name + "Native.cs"), builder.ToString().Replace("System.Void", "void")); } }
/// <summary> /// Creates the factory from the given abstract factory type /// </summary> /// <exception cref="InvalidFactoryRegistrationException">Factory registration is invalid</exception> /// <exception cref="IllegalAbstractMethodCreationException">Creation of abstract methods are illegal in their current state</exception> private void CreateFactory(IIocContainer container) { List <MethodInfo> createMethods = InterfaceType.GetMethods().Where(m => m.ReturnType != typeof(void)).ToList(); if (!createMethods.Any()) { throw new InvalidFactoryRegistrationException($"Factory {Name} has no create methods."); } Type type = typeof(TypedFactory <>); Type factory = type.MakeGenericType(InterfaceType); Factory = (ITypedFactory <TFactory>)Activator.CreateInstance(factory); AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory"); TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{InterfaceType.Name}"); typeBuilder.AddInterfaceImplementation(InterfaceType); //add `private readonly IIocContainer _container` field FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IIocContainer), FieldAttributes.Private | FieldAttributes.InitOnly); //add ctor ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IIocContainer) }); ILGenerator constructorGenerator = constructorBuilder.GetILGenerator(); constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_1); constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field constructorGenerator.Emit(OpCodes.Ret); foreach (MethodInfo createMethod in createMethods) { //create a method that looks like this //public `createMethod.ReturnType` Create(`createMethod.GetParameters()`) //{ // return IIocContainer.Resolve(`createMethod.ReturnType`, params); //} ParameterInfo[] args = createMethod.GetParameters(); MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray()); typeBuilder.DefineMethodOverride(methodBuilder, createMethod); ILGenerator generator = methodBuilder.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, containerFieldBuilder); if (args.Any()) { generator.Emit(OpCodes.Ldc_I4_S, args.Length); generator.Emit(OpCodes.Newarr, typeof(object)); for (int i = 0; i < args.Length; i++) { generator.Emit(OpCodes.Dup); generator.Emit(OpCodes.Ldc_I4_S, i); generator.Emit(OpCodes.Ldarg_S, i + 1); generator.Emit(OpCodes.Box, args[i].ParameterType); //Boxing is only needed for simple datatypes, but for now it is not a problem to box everything generator.Emit(OpCodes.Stelem_Ref); } } else { #if NET45 generator.Emit(OpCodes.Ldc_I4_0); generator.Emit(OpCodes.Newarr, typeof(object)); #elif NETSTANDARD MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))?.MakeGenericMethod(typeof(object)); generator.EmitCall(OpCodes.Call, emptyArray, null); #endif } generator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.Resolve), new[] { typeof(object[]) })?.MakeGenericMethod(createMethod.ReturnType), null); generator.Emit(OpCodes.Castclass, createMethod.ReturnType); generator.Emit(OpCodes.Ret); } //if factory contains a method to clear multiton instances MethodInfo multitonClearMethod = InterfaceType.GetMethods().FirstOrDefault(m => m.Name.Equals(CLEAR_MULTITON_INSTANCE_METHOD_NAME)); if (multitonClearMethod != null) { //create a method that looks like this //public void ClearMultitonInstance<typeToClear>() //{ // IIocContainer.ClearMultitonInstances<typeToClear>(); //} if (multitonClearMethod.IsGenericMethod) { Type typeToClear = multitonClearMethod.GetGenericArguments().FirstOrDefault(); if (typeToClear == null) { throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); } MethodBuilder multitonClearMethodBuilder = typeBuilder.DefineMethod(multitonClearMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, multitonClearMethod.ReturnType, null); multitonClearMethodBuilder.DefineGenericParameters(typeToClear.Name); typeBuilder.DefineMethodOverride(multitonClearMethodBuilder, multitonClearMethod); ILGenerator multitonClearGenerator = multitonClearMethodBuilder.GetILGenerator(); multitonClearGenerator.Emit(OpCodes.Ldarg_0); multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder); multitonClearGenerator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.ClearMultitonInstances))?.MakeGenericMethod(typeToClear), null); multitonClearGenerator.Emit(OpCodes.Ret); } else { throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); } } Factory.Factory = (TFactory)Activator.CreateInstance(typeBuilder.CreateTypeInfo().AsType(), container); }