/// <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); }
/// <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); }