Exemplo n.º 1
0
 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);
         }
     }
 }
Exemplo n.º 2
0
        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;
            }
        }
Exemplo n.º 3
0
        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);
                }
            }
        }
Exemplo n.º 4
0
        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"));
            }
        }
Exemplo n.º 5
0
        /// <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);
        }