Ejemplo n.º 1
0
        /// <summary>
        /// Clones the provided type definition from one assembly to the other.
        /// </summary>
        /// <param name="sourceType">The type to clone.</param>
        /// <param name="targetModule">The module where the type should be added to.</param>
        /// <param name="methodCloneOrder">Cecil crashes when methods are added in wrong order. You must manually sort your methods in their reverse execution order if they depend on each other. I'm sure that this problem can be solved, but for now this implementation is "good enough" for me.</param>
        /// <param name="nameSpace">The namespace to use. Leave null to use same namespace as in sourceType</param>
        /// <param name="className">The classname to use. Leave null to use same classname as in sourceType</param>
        /// <returns>The cloned type, already added to the targetModule.</returns>
        public static TypeDefinition CloneTo(TypeDefinition sourceType, ModuleDefinition targetModule, string[] methodCloneOrder, string nameSpace = null, string className = null)
        {
            if (sourceType == null)
            {
                throw new ArgumentNullException(nameof(sourceType));
            }

            try
            {
                var cloner = new TypeCloner(sourceType, targetModule, methodCloneOrder, nameSpace, className);
                return(cloner.ClonedType);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"Type cloning failed. Unable to clone {sourceType.Name} to module {targetModule.Name} as {nameSpace}.{className}", ex);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// When called will inject the <see cref="InjectedResourceLoader"/> type int the provided assembly.
        /// Then returns the <see cref="InjectedResourceLoader.Attach"/> method.
        /// </summary>
        /// <param name="definition">The assembly where the type should be added to.</param>
        /// <returns>A public, static method with no arguments that was added to the assembly.</returns>
        public static MethodDefinition InjectEmbeddedResourceLoader(AssemblyDefinition definition)
        {
            if (definition == null)
            {
                throw new ArgumentNullException("definition");
            }
            var          type         = typeof(InjectedResourceLoader);
            var          asm          = Assembly.GetAssembly(type);
            var          module       = ModuleDefinition.ReadModule(asm.GetLocation());
            const string nameSpace    = "ResourceEmbedderCompilerGenerated";
            const string className    = "ResourceEmbedderILInjected";
            const string initMethod   = "Attach";
            var          existingType = definition.MainModule.GetTypes().FirstOrDefault(t => t.Namespace == nameSpace && t.Name == className);

            if (existingType != null)
            {
                // type already injected
                var existingMethod = existingType.Methods.FirstOrDefault(m => m.Name == initMethod);
                if (existingMethod == null)
                {
                    throw new MissingMethodException(string.Format("Found type {0}, but it does not have required method {1}. This indicates that you most likely created the method yourself. Please pick another class name.", className, initMethod));
                }
                return(existingMethod);
            }
            var clonedType = TypeCloner.CloneTo(module.GetType(type.FullName), definition.MainModule, new[]
            {
                "FindMainAssembly",
                "LoadFromResource",
                "IsLocalizedAssembly",
                "AssemblyResolve",
                initMethod
            }, nameSpace, className);

            // add the type to the assembly.
            definition.MainModule.Types.Add(clonedType);
            // return the method
            return(clonedType.Methods.First(m => m.Name == initMethod));
        }