コード例 #1
0
        MethodDef CreateGetVariableAddress()
        {
            var method = new MethodDefUser(ExpressionCompilerConstants.GetVariableAddressMethodName, null, methodImplAttributes, methodAttributes);
            var sig    = MethodSig.CreateStaticGeneric(1, new PtrSig(new GenericMVar(0, method)), corlibTypes.String);

            method.MethodSig = sig;
            method.GenericParameters.Add(new GenericParamUser(0, GenericParamAttributes.NonVariant, "T"));
            method.ParamDefs.Add(new ParamDefUser("name", 1));
            method.Body = CreateBody();
            return(method);
        }
コード例 #2
0
        /// <summary>
        /// Convert some method data into a method signature.
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>Signature</returns>
        MethodSig GetMethodSig(MethodData data)
        {
            TypeSig returnType = ResolveType(data.ReturnType);

            TypeSig[] paramTypes = new TypeSig[data.Parameters.Length];
            for (Int32 i = 0; i < paramTypes.Length; i++)
            {
                paramTypes[i] = ResolveType(data.Parameters[i]);
            }

            UInt32 genericTypeCount = (UInt32)data.GenericArguments.Length;

            MethodSig methodSig;

            if (genericTypeCount == 0)
            {
                if (data.IsStatic)
                {
                    methodSig = MethodSig.CreateStatic(returnType, paramTypes);
                }
                else
                {
                    methodSig = MethodSig.CreateInstance(returnType, paramTypes);
                }
            }
            else
            {
                if (data.IsStatic)
                {
                    methodSig = MethodSig.CreateStaticGeneric(genericTypeCount, returnType, paramTypes);
                }
                else
                {
                    methodSig = MethodSig.CreateInstanceGeneric(genericTypeCount, returnType, paramTypes);
                }
            }

            return(methodSig);
        }
コード例 #3
0
        IList <MethodSig> PossibleMethodSigs(ITypeDefOrRef declaringType, MethodSig sig, MethodData data)
        {
            // Setup generic types
            IList <TypeSig> typeGenerics = new List <TypeSig>(), methodGenerics = new List <TypeSig>();

            // Add all declaring spec generic types
            TypeSpec declaringSpec = declaringType as TypeSpec;

            if (declaringSpec != null)
            {
                var genericInstSig = declaringSpec.TryGetGenericInstSig();
                foreach (var garg in genericInstSig.GenericArguments)
                {
                    typeGenerics.Add(garg);
                }
            }

            // Add all method generic types
            if (data.HasGenericArguments)
            {
                foreach (var operand in data.GenericArguments)
                {
                    var gtype = this.ResolveType_NoLock(operand.Position);
                    methodGenerics.Add(gtype.ToTypeSig());
                }
            }

            // Todo: Combinations factoring in the possibility that return type might match
            // a generic type
            TypeSig         returnType  = ResolveType(data.ReturnType);
            IList <TypeSig> returnTypes = GenericUtils.PossibleTypeSigs(returnType, typeGenerics, methodGenerics);

            TypeSig[] paramTypes = new TypeSig[data.Parameters.Length];
            for (Int32 i = 0; i < paramTypes.Length; i++)
            {
                paramTypes[i] = ResolveType(data.Parameters[i]);
            }

            UInt32 genericTypeCount = (UInt32)data.GenericArguments.Length;

            IList <MethodSig> signatures = new List <MethodSig>();
            var paramCombos = GenericUtils.CreateGenericParameterCombinations(paramTypes, typeGenerics, methodGenerics);

            foreach (var rType in returnTypes)
            {
                foreach (var combo in paramCombos)
                {
                    var paramCombo = combo.ToArray();

                    MethodSig methodSig;

                    if (genericTypeCount == 0)
                    {
                        if (data.IsStatic)
                        {
                            methodSig = MethodSig.CreateStatic(rType, paramCombo);
                        }
                        else
                        {
                            methodSig = MethodSig.CreateInstance(rType, paramCombo);
                        }
                    }
                    else
                    {
                        if (data.IsStatic)
                        {
                            methodSig = MethodSig.CreateStaticGeneric(genericTypeCount, rType, paramCombo);
                        }
                        else
                        {
                            methodSig = MethodSig.CreateInstanceGeneric(genericTypeCount, rType, paramCombo);
                        }
                    }

                    signatures.Add(methodSig);
                }
            }

            return(signatures);
        }
コード例 #4
0
        public static void Run()
        {
            // This is the file that will be created
            string newFileName = @"GenericExample2.exe";

            // Create the module
            var mod = new ModuleDefUser("GenericExample2", Guid.NewGuid(),
                                        new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName)));

            // It's a console app
            mod.Kind = ModuleKind.Console;
            // Create the assembly and add the created module to it
            new AssemblyDefUser("GenericExample2", new Version(1, 2, 3, 4)).Modules.Add(mod);

            // Add the startup type. It derives from System.Object.
            TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef);

            startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout |
                                     TypeAttributes.Class | TypeAttributes.AnsiClass;
            // Add the type to the module
            mod.Types.Add(startUpType);

            // Create the entry point method
            MethodDef entryPoint = new MethodDefUser("Main",
                                                     MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String)));

            entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static |
                                    MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
            entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
            // Name the 1st argument (argument 0 is the return type)
            entryPoint.ParamDefs.Add(new ParamDefUser("args", 1));
            // Add the method to the startup type
            startUpType.Methods.Add(entryPoint);
            // Set module entry point
            mod.EntryPoint = entryPoint;

            // Create System.Console type reference
            var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console");
            // Create 'void System.Console.WriteLine(string,object)' method reference
            var writeLine2 = new MemberRefUser(mod, "WriteLine",
                                               MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String,
                                                                      mod.CorLibTypes.Object),
                                               systemConsole);

            var assemblyRef = mod.CorLibTypes.AssemblyRef;
            // Create 'System.Collections.ObjectModel.ReadOnlyCollection`1' type ref
            var roCollectionRef = new TypeRefUser(mod, "System.Collections.ObjectModel", "ReadOnlyCollection`1", assemblyRef);
            // Create 'ReadOnlyCollection<!!0>' signature for return type
            var roCollectionSig = new GenericInstSig(new ClassSig(roCollectionRef), new GenericMVar(0));             // Return type

            // Create 'ReadOnlyCollection<Int32>' type spec
            var roCollectionTypeSpec = new TypeSpecUser(new GenericInstSig(new ClassSig(roCollectionRef), mod.CorLibTypes.Int32));
            // Create 'ReadOnlyCollection<Int32>.get_Count()' method reference
            var roCollectionGetCount = new MemberRefUser(mod, "get_Count",
                                                         MethodSig.CreateInstance(mod.CorLibTypes.Int32),
                                                         roCollectionTypeSpec);

            // Create 'System.Array' type ref
            var arrayRef = new TypeRefUser(mod, "System", "Array", assemblyRef);
            // Create 'ReadOnlyCollection<T> Array.AsReadOnly<T>(T[] array)' method reference
            // Apparently CreateStaticGeneric should be used only if at least one GenericMVar is used? Not 100% certain.
            var asReadOnly = new MemberRefUser(mod, "AsReadOnly",
                                               MethodSig.CreateStaticGeneric(1, roCollectionSig, new SZArraySig(new GenericMVar(0))),
                                               arrayRef);
            // Create 'Array.AsReadOnly<Int32>' method spec
            var asReadOnlySpec = new MethodSpecUser(asReadOnly,
                                                    new GenericInstMethodSig(mod.CorLibTypes.Int32));

            // Create 'ReadOnlyCollection<Int32>' signature for local
            var roCollectionInt32 = roCollectionTypeSpec.TryGetGenericInstSig();

            // Method body locals
            IList <Local> locals = new List <Local>();

            locals.Add(new Local(new SZArraySig(mod.CorLibTypes.Int32))); // local[0]: Int32[]
            locals.Add(new Local(roCollectionInt32));                     // local[1]: class [mscorlib]System.Collections.ObjectModel.ReadOnlyCollection`1<Int32>

            var body = new CilBody(true, new List <Instruction>(), new List <ExceptionHandler>(), locals);

            // array = new Int32[2];
            body.Instructions.Add(OpCodes.Ldc_I4_2.ToInstruction());
            body.Instructions.Add(OpCodes.Newarr.ToInstruction(mod.CorLibTypes.Int32));
            body.Instructions.Add(OpCodes.Stloc_0.ToInstruction());             // Store array to local[0]

            // array[0] = 5;
            body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction());
            body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction());
            body.Instructions.Add(OpCodes.Ldc_I4_5.ToInstruction());
            body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction());

            // array[1] = 111;
            body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction());
            body.Instructions.Add(OpCodes.Ldc_I4_1.ToInstruction());
            body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(111));
            body.Instructions.Add(OpCodes.Stelem_I4.ToInstruction());

            // collection = Array.AsReadOnly<Int32>(array)
            body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction());
            body.Instructions.Add(OpCodes.Call.ToInstruction(asReadOnlySpec));
            body.Instructions.Add(OpCodes.Stloc_1.ToInstruction());

            // Console.WriteLine("Count: {0}", collection.Count)
            body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Count: {0}"));
            body.Instructions.Add(OpCodes.Ldloc_1.ToInstruction());
            body.Instructions.Add(OpCodes.Callvirt.ToInstruction(roCollectionGetCount));
            body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32));
            body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2));

            // return 0;
            body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction());
            body.Instructions.Add(OpCodes.Ret.ToInstruction());

            entryPoint.Body = body;

            // Save the assembly
            mod.Write(newFileName);
        }