public CompMethodsInAssemblyType SameAppDomainCompile(string code, bool addSelfAttach = true) { if (addSelfAttach) { code = SourceManipulation.AddSelfAttachToSource(code); } Assembly ass = Compilation.GenerateAssemblyInMemory(code, false); CompMethodsInAssemblyType funcs = Compilation.GenerateAllMethodsFromAssembly(ass); return(funcs); }
/// <summary> /// Registers a compile time mono to given target. /// </summary> /// <param name="target">Target to which to attach the runtime mono.</param> /// <param name="funcs">Mono information: name, methods and pramaters.</param> /// <returns></returns> public MonoBehaviour AttachCompiletimeMono(GameObject target, CompMethodsInAssemblyType funcs, MonoBehaviour mono, string source) { /// Attaches the given mono and registeres in attachedMonos var monoData = this.AttachAndAddToDict(funcs, target, mono); /// If a mono with the same name exists and the method singnature changed send it to the UI to redraw it. if (monoData.changesInMethodSignature) { ReferenceBuffer.Instance.ManageProcUI.RegisterNewOrChangedMono(this.GenerateButtonInformation(monoData, target, source)); monoData.changesInMethodSignature = false; } return(null); }
/// <summary> /// Does two things: /// If attach is true, it attaches the mono to the target and registeres it in attachedMonos /// If attach is false, means that the script is already attached and it only regerteres it in the same collection. /// Also if there is a mono with that name already, it remeves the old one and registeres the new one. /// </summary> /// <param name="funcs"></param> /// <param name="target"></param> /// <param name="attach"></param> /// <param name="alreadyAttachedMono"> If null we need to attach what is passed. If not null - this is the mono that is already attached!</param> /// <returns></returns> private TargetManagerMonoWithNameAndMethods AttachAndAddToDict( CompMethodsInAssemblyType funcs, GameObject target, MonoBehaviour alreadyAttachedMono) { this.CreateMonoDataIfNoneExists(target); /// Getting exsiting monos for target. List <TargetManagerMonoWithNameAndMethods> existingMonosForTarget = this.attachedMonos[target]; TargetManagerMonoWithNameAndMethods preexistingMono = GetPreexistingMonoWithSameName(target, funcs, existingMonosForTarget); this.DestroyIfMonoWithSameNameAttached(preexistingMono, target, funcs, existingMonosForTarget); MonoBehaviour attachedMono = alreadyAttachedMono == null?funcs.Attach(target) : alreadyAttachedMono; TargetManagerMonoWithNameAndMethods newMonoData = new TargetManagerMonoWithNameAndMethods(funcs.TypeName, attachedMono); newMonoData.Methods = funcs.MethodInfos.Select(x => new TargetManagerMethodInfoWithName { MethodInfo = x.Value.MethodInfo, Parameters = x.Value.Parameters, Name = x.Value.MethodInfo.Name, }).ToList(); newMonoData.changesInMethodSignature = this.AreThereChangesInSignature(newMonoData, preexistingMono); /// Adding it to the collection for the given target. existingMonosForTarget.Add(newMonoData); /// Passing the if (alreadyAttachedMono == null) { ReferenceBuffer.Instance.Level.RegisterUpdatedMono(newMonoData); } return(newMonoData); }
/// <summary> /// Recives a type and extracts the type name, /// attach function - function that recives game object and returns monobehaviour, /// as well as all methods with paramater types <see cref=CompMethodsInAssemblyType> /// </summary> public static CompMethodsInAssemblyType GenerateAllMethodsFromMonoType(Type type) { var result = new CompMethodsInAssemblyType(); ///Getting the attach method and converting it to Funk that attaches to GameObject and returns the MonoBehaviour var attachMethod = type.GetMethod("Attach"); ///if no attachMethod throw if (attachMethod == null) { Debug.Log("There is not attach method on Type: " + type.Name); ///TODO: I also use this to get methods for compile time types that do not need attaching ///separate both use cases? //throw new Exception("There is not attach method on Type: " + type.Name); } else { ///Creating the attach function if we find Attach method in the type ///The attach method is used to attach the monobehaviour to GameObject and return the attached Instance var attachFunk = (Func <GameObject, MonoBehaviour>) Delegate.CreateDelegate(typeof(Func <GameObject, MonoBehaviour>), attachMethod); result.Attach = attachFunk; } /// Setting the flags for method extraction var flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance; if (Settings.CompilationIncludePrivate) { flags = flags | BindingFlags.NonPublic; } if (Settings.CompilationIncludeStatic) { flags = flags | BindingFlags.Static; } ///... ///Non Attach methods are gathered here var otherMethods = type.GetMethods(flags) .Where(x => x.Name != "Attach"); ///Gathering the information for method parameters var methodInfos = new Dictionary <string, CompMethodInfoWIthParams>(); foreach (var methodInfo in otherMethods) { var parameterInfos = methodInfo.GetParameters(); var parameters = new List <UiParameterWithType>(); foreach (var parInfo in parameterInfos) { parameters.Add(new UiParameterWithType { Name = parInfo.Name, Type = parInfo.ParameterType }); } methodInfos[methodInfo.Name] = new CompMethodInfoWIthParams { MethodInfo = methodInfo, Parameters = parameters.ToArray(), }; } ///... result.MethodInfos = methodInfos; result.TypeName = type.Name; return(result); }
private TargetManagerMonoWithNameAndMethods GetPreexistingMonoWithSameName(GameObject target, CompMethodsInAssemblyType funcs, List <TargetManagerMonoWithNameAndMethods> existingMonosForTarget) { /// Cheking if there is more than one script with given name already registered which should never happen. TargetManagerMonoWithNameAndMethods[] existingMonos = existingMonosForTarget.Where(x => x.Name == funcs.TypeName).ToArray(); if (existingMonos.Length > 1) { Debug.Log($"There are more that 1 scripts with name {funcs.TypeName} already attached!"); Debug.Break(); return(null); } if (existingMonos.Length == 0) { return(null); } ///We have exactly one TargetManagerMonoWithNameAndMethods previousMono = existingMonos[0]; return(previousMono); }
private void DestroyIfMonoWithSameNameAttached(TargetManagerMonoWithNameAndMethods preexistingMono, GameObject target, CompMethodsInAssemblyType funcs, List <TargetManagerMonoWithNameAndMethods> existingMonosForTarget) { /// If a mono with the same name is attched, we destroy the old one! if (preexistingMono != null) { Component monoToDestroy = target.GetComponent(preexistingMono.Mono.GetType()); GameObject.Destroy(monoToDestroy); existingMonosForTarget.Remove(existingMonosForTarget.SingleOrDefault(x => x.Name == funcs.TypeName)); Debug.Log("Old Script is overriden"); } }