Beispiel #1
0
        /// <summary>
        /// Loads the PatchInfo type of the specified name from the specified assembly, but in a separate AppDomain to facilitate unloading. Returns a special proxy object.
        /// </summary>
        /// <param name="assemblyLocation">The full path to the assembly in question. Required for locating the assembly.</param>
        /// <param name="assemblyName">The expected short name of the assembly. This parameter is mainly optional and is only used for diagonostics.</param>
        /// <param name="fullTypeName">The full name of the type to be instantiated.</param>
        /// <returns></returns>
        internal static PatchInfoProxy FromPatchAssembly(string assemblyLocation, string assemblyName, string fullTypeName)
        {
            var domainSetup = new AppDomainSetup()
            {
                ApplicationBase = Environment.CurrentDirectory
            };
            var appDomain      = AppDomain.CreateDomain(assemblyName, AppDomain.CurrentDomain.Evidence, domainSetup);
            var myType         = typeof(PatchInfoProxy);
            var theActualProxy = (PatchInfoProxy)appDomain.CreateInstanceAndUnwrap(myType.Assembly.FullName, myType.FullName, false,
                                                                                   CommonBindingFlags.Everything, null, null, null, null);

            theActualProxy.SetInnerInfo(assemblyLocation, fullTypeName);

            var proxyProxy = new PatchInfoProxy()
            {
                Domain           = appDomain,
                Info             = theActualProxy,
                AssemblyName     = assemblyName,
                AssemblyLocation = assemblyLocation,
                FullTypeName     = fullTypeName
            };

            return(proxyProxy);
        }
Beispiel #2
0
        /// <summary>
        /// Reads the specified assembly definition and creates a manifest.
        /// </summary>
        /// <param name="yourAssembly">The patch assembly to read.</param>
        /// <returns></returns>
        public PatchingManifest CreateManifest(AssemblyDefinition yourAssembly)
        {
            var multicast = yourAssembly.GetCustomAttributes <DisablePatchingByNameAttribute>();
            var filter    = CreateMemberFilter(multicast);

            var patchAssemblyAttr = yourAssembly.GetCustomAttribute <PatchAssemblyAttribute>();

            if (patchAssemblyAttr == null)
            {
                throw Errors.No_patch_assembly_attribute(yourAssembly);
            }
            var patchInfoTypeRefs =
                yourAssembly.MainModule.Types.Where(
                    x => x.CustomAttributes.Any(y => y.AttributeType.FullName == typeof(PatchInfoAttribute).FullName))
                .ToList
                    ();

            if (patchInfoTypeRefs.Count > 1)
            {
                throw Errors.More_than_one_PatchInfoAttribute(yourAssembly);
            }
            var infoTypeRef = patchInfoTypeRefs.FirstOrDefault();

            PatchInfoProxy info = null;

            if (infoTypeRef != null)
            {
                var infoTypeDef = infoTypeRef.Resolve();
                info = PatchInfoProxy.FromPatchAssembly(infoTypeDef.Module.FullyQualifiedName, infoTypeDef.Module.Assembly.Name.Name,
                                                        infoTypeDef.FullName);
                Log.Information("PatchInfo class successfuly loaded.");
            }
            else
            {
                Log.Warning($"This assembly does not have a class decorated with {nameof(PatchInfoAttribute)} so it cannot participate in automatic patching.");
            }

            var allTypesInOrder = GetAllTypesInNestingOrder(yourAssembly.MainModule.Types).ToList();
            //+ Organizing types by action attribute
            var typesByActionSeq =
                from type in allTypesInOrder
                let typeActionAttr = GetTypeActionAttribute(type)
                                     where typeActionAttr != null && Filter(type) && filter(type)
                                     let patchedTypeName = type.GetPatchedTypeFullName()
                                                           group new TypeAction()
            {
                YourType        = type,
                ActionAttribute = typeActionAttr,
            } by typeActionAttr.GetType();

            var types = typesByActionSeq.ToSimpleTypeLookup();

            var fields     = OrganizeMembers(types, x => x.Fields, filter);
            var methods    = OrganizeMembers(types, x => x.Methods, filter);
            var properties = OrganizeMembers(types, x => x.Properties, filter);
            var events     = OrganizeMembers(types, x => x.Events, filter);

            foreach (var eventAction in events[typeof(NewMemberAttribute)])
            {
                ImplicitlyAddNewMethods(methods, eventAction, vent => {
                    return(new[] {
                        vent.AddMethod,
                        vent.RemoveMethod,
                        vent.InvokeMethod,
                    }.Concat(vent.OtherMethods).Where(method => method != null));
                });
            }

            foreach (var propAction in properties[typeof(NewMemberAttribute)])
            {
                ImplicitlyAddNewMethods(methods, propAction, prop => {
                    return(new[] {
                        prop.GetMethod,
                        prop.SetMethod,
                    }.Concat(prop.OtherMethods).Where(method => method != null));
                });
            }

            var patchingManifest = new PatchingManifest()
            {
                EventActions    = events,
                FieldActions    = fields,
                PropertyActions = properties,
                MethodActions   = methods,
                TypeActions     = types,
                PatchAssembly   = yourAssembly,
                PatchInfo       = info
            };

            return(patchingManifest);
        }