Beispiel #1
0
        public ProviderMethodBindingGenerator(
            ModuleDefinition moduleDefinition,
            References references,
            TypeReference moduleType,
            MethodDefinition providerMethod,
            bool isLibrary)
            : base(moduleDefinition, references)
        {
            this.providerMethod = providerMethod;
            this.moduleType     = moduleType;
            this.isLibrary      = isLibrary;

            var name = ProviderMethod.GetNamedAttributeName();

            key = CompilerKeys.ForType(ProviderMethod.ReturnType, name);

            var attr = providerMethod.CustomAttributes.First(Attributes.IsProvidesAttribute);

            if (attr.HasConstructorArguments)
            {
                var providesTypeArg = attr.ConstructorArguments.Single();
                ProvidesType = (ProvidesType)providesTypeArg.Value;
            }
            else
            {
                ProvidesType = ProvidesType.Default;
            }
        }
Beispiel #2
0
 private InjectMemberInfo(string key, TypeReference type)
 {
     this.key = key;
     this.type = type;
     lazyKey = CompilerKeys.GetLazyKey(key);
     providerKey = CompilerKeys.GetProviderKey(key);
 }
Beispiel #3
0
        private IDictionary <string, Binding> ProcessCompleteModule(ModuleGenerator moduleGenerator, bool ignoreCompletenessErrors)
        {
            var bindings   = new Dictionary <string, Binding>(StringComparer.Ordinal);
            var overrides  = new Dictionary <string, Binding>(StringComparer.Ordinal);
            var allModules = new Dictionary <string, ModuleGenerator>(StringComparer.Ordinal);
            var hasError   = false;

            GatherIncludedModules(moduleGenerator, allModules, new Stack <string>());

            var resolver = new Resolver(null, plugin, errors =>
            {
                if (ignoreCompletenessErrors)
                {
                    return;
                }

                hasError = true;
                foreach (var e in errors)
                {
                    errorReporter.LogError(e);
                }
            });

            foreach (var module in allModules.Values)
            {
                // Request entry-point bindings
                var addTo = module.IsOverride ? overrides : bindings;

                foreach (var entryPointType in module.EntryPoints)
                {
                    var key = entryPointType.Resolve().IsInterface
                                  ? CompilerKeys.ForType(entryPointType)
                                  : CompilerKeys.GetMemberKey(entryPointType);
                    resolver.RequestBinding(key, module.ModuleType.FullName, false, true);
                }

                foreach (var providerGenerator in module.ProviderGenerators)
                {
                    var binding = new CompilerProvidesBinding(providerGenerator);

                    if (addTo.ContainsKey(binding.ProviderKey))
                    {
                        var message  = "Duplicate bindings for {0} in {1}{2}.";
                        var addendum = module.IsOverride ? "overriding module " : string.Empty;

                        throw new ValidationException(string.Format
                                                          (message, binding.ProviderKey, addendum, module.ModuleType.FullName));
                    }

                    addTo.Add(binding.ProviderKey, binding);
                }
            }

            resolver.InstallBindings(bindings);
            resolver.InstallBindings(overrides);
            var allBindings = resolver.ResolveAllBindings();

            return(hasError ? null : allBindings);
        }
Beispiel #4
0
        private void EmitCtor(TypeDefinition runtimeModule)
        {
            /**
             * public CompiledRuntimeModule()
             *     : base(typeof(OriginalModule),
             *            new[] { "key0", ..., "keyN" },
             *            new[] { typeof(IncludedModule0), ..., typeof(IncludedModuleN) },
             *            isComplete,
             *            isLibrary)
             * {
             * }
             */

            var ctor = new MethodDefinition(".ctor",
                                            MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                            References.Void);

            var il = ctor.Body.GetILProcessor();

            // Push args (this, moduleType, entryPoints, includes, complete, library) and call base ctor
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldtoken, importedModuleType);
            il.Emit(OpCodes.Call, References.Type_GetTypeFromHandle);

            // make array of entry point keys
            il.Emit(OpCodes.Ldc_I4, Injects.Count);
            il.Emit(OpCodes.Newarr, References.String);
            for (var i = 0; i < Injects.Count; ++i)
            {
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Ldc_I4, i);
                il.Emit(OpCodes.Ldstr, CompilerKeys.GetMemberKey(Injects[i]));
                il.Emit(OpCodes.Stelem_Ref);
            }

            // make array of included module types
            il.Emit(OpCodes.Ldc_I4, IncludedModules.Count);
            il.Emit(OpCodes.Newarr, References.Type);
            for (var i = 0; i < IncludedModules.Count; ++i)
            {
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Ldc_I4, i);
                il.Emit(OpCodes.Ldtoken, Import(IncludedModules[i]));
                il.Emit(OpCodes.Call, References.Type_GetTypeFromHandle);
                il.Emit(OpCodes.Stelem_Ref);
            }

            il.EmitBoolean(IsComplete);
            il.EmitBoolean(IsLibrary);
            il.EmitBoolean(IsOverride);

            il.Emit(OpCodes.Call, References.RuntimeModule_Ctor);
            il.Emit(OpCodes.Ret);

            runtimeModule.Methods.Add(ctor);
            generatedCtor = ctor;
        }
        public ProviderMethodBindingGenerator(
            ModuleDefinition moduleDefinition,
            References references,
            TypeDefinition moduleType,
            MethodDefinition providerMethod,
            bool isLibrary)
            : base(moduleDefinition, references)
        {
            this.providerMethod = Conditions.CheckNotNull(providerMethod, "providerMethod");
            this.moduleType     = Conditions.CheckNotNull(moduleType, "moduleType");
            this.isLibrary      = isLibrary;

            var name = ProviderMethod.GetNamedAttributeName();

            key = CompilerKeys.ForType(ProviderMethod.ReturnType, name);
        }
Beispiel #6
0
        public override void Validate(IErrorReporter errorReporter)
        {
            ParamKeys = new List <string>();
            foreach (var param in ProviderMethod.Parameters)
            {
                ParamKeys.Add(CompilerKeys.ForParam(param));
            }

            if (ProviderMethod.HasGenericParameters)
            {
                errorReporter.LogError("Provider methods cannot be generic: " + ProviderMethod.FullName);
            }

            if (ProviderMethod.IsStatic)
            {
                errorReporter.LogError("Provider methods cannot be static: " + ProviderMethod.FullName);
            }

            if (ProviderMethod.MethodReturnType.ReturnType.Name == "Lazy`1")
            {
                errorReporter.LogError("Provider methods cannot return System.Lazy<T> directly: " + ProviderMethod.FullName);
            }

            if (ProviderMethod.ReturnType.Name == "IProvider`1")
            {
                errorReporter.LogError("Provider methods cannot return IProvider<T> directly: " + ProviderMethod.FullName);
            }

            if (ProviderMethod.IsPrivate)
            {
                errorReporter.LogError("Provider methods cannot be private: " + ProviderMethod.FullName);
            }

            if (ProviderMethod.IsAbstract)
            {
                errorReporter.LogError("Provider methods cannot be abstract: " + ProviderMethod.FullName);
            }
        }
Beispiel #7
0
        public override TypeDefinition Generate(IErrorReporter errorReporter)
        {
            Conditions.CheckNotNull(RuntimeModuleType, "RuntimeModuleType");
            var providerType = new TypeDefinition(
                RuntimeModuleType.Namespace,
                "ProviderBinding_" + RuntimeModuleType.NestedTypes.Count,
                TypeAttributes.NestedPublic,
                References.Binding);

            providerType.CustomAttributes.Add(new CustomAttribute(References.CompilerGeneratedAttribute));
            providerType.DeclaringType = RuntimeModuleType;

            IsSingleton = ProviderMethod.CustomAttributes.Any(Attributes.IsSingletonAttribute);
            var moduleField = new FieldDefinition("module", FieldAttributes.Private, ModuleType);

            providerType.Fields.Add(moduleField);

            var parameters = new List <ParameterDefinition>();
            var fields     = new List <FieldDefinition>();

            foreach (var param in ProviderMethod.Parameters)
            {
                var field = new FieldDefinition(param.Name, FieldAttributes.Private, References.Binding);
                providerType.Fields.Add(field);
                parameters.Add(param);
                fields.Add(field);
                ParamKeys.Add(CompilerKeys.ForParam(param));
            }

            EmitCtor(providerType, moduleField);
            EmitResolve(providerType, parameters, fields);
            EmitGetDependencies(providerType, fields);
            EmitGet(providerType, moduleField, parameters, fields);

            RuntimeModuleType.NestedTypes.Add(providerType);

            return(providerType);
        }
Beispiel #8
0
        public void ValidateCompleteness(ISet <string> injectableKeys, IErrorReporter errorReporter)
        {
            if (!IsComplete)
            {
                return;
            }

            foreach (var method in baseProvidesMethods)
            {
                foreach (var param in method.Parameters)
                {
                    var name = param.Name;
                    var key  = CompilerKeys.ForParam(param);

                    if (!injectableKeys.Contains(key))
                    {
                        const string msg       = "{0}: Module is a complete module but has an unsatisfied dependency on {1}{2}";
                        var          nameDescr = name == null ? string.Empty : "[Named(\"" + name + "\")] ";
                        errorReporter.LogError(string.Format(msg, moduleType.FullName, nameDescr, param.ParameterType.FullName));
                    }
                }
            }
        }
Beispiel #9
0
 public InjectMemberInfo(PropertyDefinition property)
     : this(CompilerKeys.ForProperty(property), property.PropertyType)
 {
     memberName = property.FullName;
 }
Beispiel #10
0
 public InjectMemberInfo(ParameterDefinition param)
     : this(CompilerKeys.ForParam(param), param.ParameterType)
 {
     memberName = param.Name;
 }
Beispiel #11
0
        public override void Validate(IErrorReporter errorReporter)
        {
            if (injectedType.HasGenericParameters)
            {
                errorReporter.LogError("Open generic types may not be injected: " + injectedType.FullName);
                return;
            }

            switch (injectedType.Attributes & TypeAttributes.VisibilityMask)
            {
            case TypeAttributes.NestedFamily:
            case TypeAttributes.NestedFamANDAssem:
            case TypeAttributes.NestedPrivate:
            case TypeAttributes.NotPublic:
                // This type is not externally visible and can't be included in a compiled plugin.
                // It can still be loaded reflectively.
                IsVisibleToPlugin = false;
                errorReporter.LogWarning(injectedType.FullName + ": This type is private, and will be loaded reflectively.  Consider making it internal or public.");
                break;
            }

            Key         = CompilerKeys.ForType(injectedType);
            MembersKey  = CompilerKeys.GetMemberKey(injectedType);
            IsSingleton = injectedType.CustomAttributes.Any(Attributes.IsSingletonAttribute);

            var injectableCtors = injectedType
                                  .GetConstructors()
                                  .Where(ctor => ctor.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                  .ToList();

            foreach (var ctor in injectableCtors)
            {
                if (InjectableCtor != null)
                {
                    errorReporter.LogError(string.Format("{0} has more than one injectable constructor.", injectedType.FullName));
                }

                if (!ctor.Attributes.IsVisible())
                {
                    errorReporter.LogError("{0} has an injectable constructor, but it is not accessible.  Consider making it public.");
                }

                InjectableCtor = ctor;
            }

            InjectableProperties = injectedType
                                   .Properties
                                   .Where(p => p.DeclaringType == injectedType)
                                   .Where(p => p.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                   .Select(p => new PropertyInfo(p))
                                   .ToList();

            foreach (var p in InjectableProperties)
            {
                if (p.Setter == null)
                {
                    errorReporter.LogError(string.Format("{0} is marked [Inject] but has no setter.", p.MemberName));
                    continue;
                }

                if (!p.Setter.Attributes.IsVisible())
                {
                    const string msg = "{0}.{1} is marked [Inject], but has no visible setter.  Consider adding a public setter.";
                    errorReporter.LogError(string.Format(msg, injectedType.FullName, p.PropertyName));
                }
            }

            if (InjectableCtor == null)
            {
                if (InjectableProperties.Count == 0 && !IsEntryPoint)
                {
                    errorReporter.LogError("No injectable constructors or properties found on " + injectedType.FullName);
                }

                var defaultCtor = injectedType.GetConstructors().FirstOrDefault(ctor => !ctor.HasParameters);
                if (defaultCtor == null)
                {
                    errorReporter.LogError("Type " + injectedType.FullName + " has no [Inject] constructors and no default constructor.");
                    return;
                }

                InjectableCtor = defaultCtor;
            }

            CtorParams = InjectableCtor.Parameters.Select(p => new InjectMemberInfo(p)).ToList();

            var baseType        = injectedType.BaseType;
            var baseTypeAsmName = baseType.Maybe(type => type.Scope)
                                  .Maybe(scope => scope.Name);

            if (baseType == null ||
                baseTypeAsmName == null ||
                baseTypeAsmName.StartsWith("mscorlib") ||
                baseTypeAsmName.StartsWith("System") ||
                baseTypeAsmName.StartsWith("Microsoft") ||
                baseTypeAsmName.StartsWith("Mono"))
            {
                // We can safely skip types known not to have [Inject] bindings, i.e. types
                // from the BCL, etc.
                BaseTypeKey = null;
            }
            else
            {
                // Otherwise, base types might have [Inject] properties that we'll need
                // to account for.
                BaseTypeKey = Weaver.EnqueueBaseTypeBinding(baseType)
                    ? CompilerKeys.ForType(baseType)
                    : null;
            }
        }
Beispiel #12
0
        public override void Validate(IErrorReporter errorReporter)
        {
            if (injectedType.HasGenericParameters)
            {
                if (genericInstanceType == null ||
                    genericInstanceType.GenericArguments.Count != injectedType.GenericParameters.Count)
                {
                    errorReporter.LogError("Open generic types may not be injected: " + injectedType.FullName);
                    return;
                }
            }

            if (!injectedType.IsVisible())
            {
                // This type is not externally visible and can't be included in a compiled loader.
                // It can still be loaded reflectively.
                IsVisibleToLoader = false;
                errorReporter.LogWarning(injectedType.FullName + ": This type is private, and will be loaded reflectively.  Consider making it internal or public.");
            }

            Key         = CompilerKeys.ForType(injectedType);
            MembersKey  = CompilerKeys.GetMemberKey(injectedType);
            IsSingleton = injectedType.CustomAttributes.Any(Attributes.IsSingletonAttribute);

            var injectableCtors = injectedType
                                  .GetConstructors()
                                  .Where(ctor => ctor.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                  .ToList();

            foreach (var ctor in injectableCtors)
            {
                if (InjectableCtor != null)
                {
                    errorReporter.LogError(string.Format("{0} has more than one injectable constructor.", injectedType.FullName));
                }

                if (!ctor.IsVisible())
                {
                    errorReporter.LogError(string.Format("{0} has an injectable constructor, but it is not accessible.  Consider making it public.", injectedType.FullName));
                }

                InjectableCtor = ctor;
            }

            InjectableProperties = injectedType
                                   .Properties
                                   .Where(p => p.DeclaringType == injectedType)
                                   .Where(p => p.CustomAttributes.Any(Attributes.IsInjectAttribute))
                                   .Select(p => new PropertyInfo(p))
                                   .ToList();

            foreach (var p in InjectableProperties)
            {
                if (p.Setter == null)
                {
                    errorReporter.LogError(string.Format("{0} is marked [Inject] but has no setter.", p.MemberName));
                    continue;
                }

                if (!p.Setter.IsVisible())
                {
                    const string msg = "{0}.{1} is marked [Inject], but has no visible setter.  Consider adding a public setter.";
                    errorReporter.LogError(string.Format(msg, injectedType.FullName, p.PropertyName));
                }
            }

            if (InjectableCtor == null)
            {
                if (InjectableProperties.Count == 0 && !IsModuleInjectable)
                {
                    errorReporter.LogError("No injectable constructors or properties found on " + injectedType.FullName);
                }

                // XXX ben: this is wrong, I think - entry points with no ctor will still fail.
                var defaultCtor = injectedType.GetConstructors().FirstOrDefault(ctor => !ctor.HasParameters && ctor.IsVisible());
                if (defaultCtor == null && !IsModuleInjectable)
                {
                    errorReporter.LogError("Type " + injectedType.FullName + " has no [Inject] constructors and no default constructor.");
                    return;
                }

                InjectableCtor = defaultCtor;
            }
            // InjectableCtor is null iff this is a value-type entry-point with no default ctor.
            // It's OK, such types never get constructed, only "provided".
            CtorParams = InjectableCtor == null
                ? new List <InjectMemberInfo>()
                : InjectableCtor.Parameters.Select(p => new InjectMemberInfo(p)).ToList();

            var baseType        = injectedType.BaseType;
            var baseTypeAsmName = baseType.Maybe(type => type.Scope)
                                  .Maybe(scope => scope.Name);

            if (baseType == null ||
                baseTypeAsmName == null ||
                baseTypeAsmName.StartsWith("mscorlib") ||
                baseTypeAsmName.StartsWith("System") ||
                baseTypeAsmName.StartsWith("Microsoft") ||
                baseTypeAsmName.StartsWith("Mono"))
            {
                // We can safely skip types known not to have [Inject] bindings, i.e. types
                // from the BCL, etc.
                BaseTypeKey = null;
            }
            else
            {
                // Otherwise, base types might have [Inject] properties that we'll need
                // to account for.
                BaseTypeKey = Weaver.EnqueueBaseTypeBinding(baseType)
                    ? CompilerKeys.ForType(baseType)
                    : null;
            }
        }
Beispiel #13
0
        private IDictionary <string, Binding> ProcessCompleteModule(
            ModuleGenerator moduleGenerator,
            bool ignoreCompletenessErrors)
        {
            var bindings   = new Dictionary <string, Binding>(StringComparer.Ordinal);
            var overrides  = new Dictionary <string, Binding>(StringComparer.Ordinal);
            var allModules = new Dictionary <string, ModuleGenerator>(StringComparer.Ordinal);
            var hasError   = false;

            GatherIncludedModules(moduleGenerator, allModules, new Stack <string>());

            var resolver = new Resolver(null, loader, errors =>
            {
                if (ignoreCompletenessErrors)
                {
                    return;
                }

                hasError = true;
                foreach (var e in errors)
                {
                    errorReporter.LogError(e);
                }
            });

            foreach (var module in allModules.Values)
            {
                // Request entry-point bindings
                var addTo = module.IsOverride ? overrides : bindings;

                foreach (var injectType in module.Injects)
                {
                    var key = injectType.Resolve().IsInterface
                                  ? CompilerKeys.ForType(injectType)
                                  : CompilerKeys.GetMemberKey(injectType);

                    resolver.RequestBinding(key, module.ModuleType.FullName, false, true);
                }

                foreach (var providerGenerator in module.ProviderGenerators)
                {
                    var binding = new CompilerProvidesBinding(providerGenerator);

                    if (addTo.ContainsKey(binding.ProviderKey))
                    {
                        var message  = "Duplicate bindings for {0} in {1}{2}.";
                        var addendum = module.IsOverride ? "overriding module " : string.Empty;

                        throw new ValidationException(string.Format
                                                          (message, binding.ProviderKey, addendum, module.ModuleType.FullName));
                    }

                    switch (providerGenerator.ProvidesType)
                    {
                    case ProvidesType.Default:
                        addTo.Add(binding.ProviderKey, binding);
                        break;

                    case ProvidesType.Set:
                        var setKey = CompilerKeys.GetSetKey(binding.ProviderKey);
                        CompilerSetBinding.Add(addTo, setKey, binding);
                        break;

                    default:
                        throw new ArgumentException("Unknown ProvidesType value: " + providerGenerator.ProvidesType);
                    }
                }
            }

            resolver.InstallBindings(bindings);
            resolver.InstallBindings(overrides);
            var allBindings = resolver.ResolveAllBindings();

            return(!hasError ? allBindings : null);
        }
Beispiel #14
0
        public override void Validate(IErrorReporter errorReporter)
        {
            if (moduleType.BaseType != null && moduleType.BaseType.FullName != References.Object.FullName)
            {
                errorReporter.LogError(moduleType.FullName + ": Modules must inherit from System.Object only.");
            }

            if (moduleType.IsAbstract)
            {
                errorReporter.LogError(moduleType.FullName + ": Modules cannot be abstract.");
            }

            moduleCtor = moduleType.GetConstructors().FirstOrDefault(m => m.Parameters.Count == 0);
            if (moduleCtor == null)
            {
                errorReporter.LogError(moduleType.FullName + " is marked as a [Module], but no default constructor is visible.");
            }

            ProvidedKeys = new HashSet <string>(StringComparer.Ordinal);
            foreach (var method in baseProvidesMethods)
            {
                var name = method.GetNamedAttributeName();
                var key  = CompilerKeys.ForType(method.ReturnType, name);

                if (!ProvidedKeys.Add(key))
                {
                    errorReporter.LogError(moduleType.FullName + ": Duplicate provider key for method " + moduleType.FullName + "." + method.Name);
                }
            }

            if (IsComplete)
            {
                foreach (var method in baseProvidesMethods)
                {
                    foreach (var param in method.Parameters)
                    {
                        var name = param.GetNamedAttributeName();
                        var key  = CompilerKeys.ForType(param.ParameterType, name);

                        if (!ProvidedKeys.Contains(key))
                        {
                            const string msg       = "{0}: Module is a complete module but has an unsatisfied dependency on {1}{2}";
                            var          nameDescr = name == null ? string.Empty : "[Named(\"" + name + "\")] ";
                            errorReporter.LogError(string.Format(msg, moduleType.FullName, nameDescr, param.ParameterType.FullName));
                        }
                    }
                }
            }

            switch (moduleType.Attributes & TypeAttributes.VisibilityMask)
            {
            case TypeAttributes.NestedFamily:
            case TypeAttributes.NestedFamANDAssem:
            case TypeAttributes.NestedPrivate:
            case TypeAttributes.NotPublic:
                // This type is not externally visible and can't be included in a compiled plugin.
                // It can still be loaded reflectively.
                IsVisibleToPlugin = false;
                errorReporter.LogWarning(moduleType.FullName + ": This type is private, and will be loaded reflectively.  Consider making it internal or public.");
                break;
            }

            foreach (var gen in ProviderGenerators)
            {
                gen.Validate(errorReporter);
            }
        }
Beispiel #15
0
        private void EmitGetBindings(TypeDefinition runtimeModule)
        {
            /**
             * public override void GetBindings(Dictionary<string, Binding> bindings)
             * {
             *     var module = this.Module;
             *     bindings.Add("keyof binding0", new ProviderBinding0(module));
             *     ...
             *     bindings.Add("keyof bindingN", new ProviderBindingN(module));
             * }
             */
            var getBindings = new MethodDefinition(
                "GetBindings",
                MethodAttributes.Public | MethodAttributes.Virtual,
                References.Void);

            var vModule = new VariableDefinition("module", importedModuleType);

            getBindings.Body.Variables.Add(vModule);
            getBindings.Body.InitLocals = true;

            getBindings.Parameters.Add(new ParameterDefinition(References.DictionaryOfStringToBinding));

            var il = getBindings.Body.GetILProcessor();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Callvirt, References.RuntimeModule_ModuleGetter);
            il.Emit(OpCodes.Castclass, importedModuleType);
            il.Emit(OpCodes.Stloc, vModule);

            foreach (var binding in ProviderGenerators)
            {
                switch (binding.ProvidesType)
                {
                case ProvidesType.Default:
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldstr, binding.Key);
                    il.Emit(OpCodes.Ldloc, vModule);
                    il.Emit(OpCodes.Newobj, binding.GeneratedCtor);
                    il.Emit(OpCodes.Callvirt, References.DictionaryOfStringToBinding_Add);
                    break;

                case ProvidesType.Set:
                    var addMethodRef = new GenericInstanceMethod(References.SetBindings_AddOfT);
                    addMethodRef.GenericArguments.Add(binding.ProviderMethod.ReturnType);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldstr, CompilerKeys.GetSetKey(binding.Key));
                    il.Emit(OpCodes.Ldloc, vModule);
                    il.Emit(OpCodes.Newobj, binding.GeneratedCtor);
                    il.Emit(OpCodes.Call, addMethodRef);
                    break;

                default:
                    throw new InvalidOperationException("Unknown ProvidesType value: " + binding.ProvidesType);
                }
            }

            il.Emit(OpCodes.Ret);

            runtimeModule.Methods.Add(getBindings);
        }