| | |
| | | //返回-1表示没有标签 |
| | | static int getHotfixType(MemberInfo memberInfo) |
| | | { |
| | | try |
| | | { |
| | | foreach (var ca in memberInfo.GetCustomAttributes(false)) |
| | | { |
| | | var ca_type = ca.GetType(); |
| | |
| | | return (int)(ca_type.GetProperty("Flag").GetValue(ca, null)); |
| | | } |
| | | } |
| | | } |
| | | catch { } |
| | | return -1; |
| | | } |
| | | |
| | |
| | | IgnoreProperty = 4, |
| | | IgnoreNotPublic = 8, |
| | | Inline = 16, |
| | | IntKey = 32 |
| | | IntKey = 32, |
| | | AdaptByDelegate = 64, |
| | | IgnoreCompilerGenerated = 128, |
| | | NoBaseProxy = 256, |
| | | } |
| | | |
| | | static class ExtentionMethods |
| | |
| | | { |
| | | bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing); |
| | | |
| | | bool isIntKey = hotfixType.HasFlag(HotfixFlagInTool.IntKey) && !method.DeclaringType.HasGenericParameters && isTheSameAssembly; |
| | | |
| | | bool isAdaptByDelegate = !isIntKey && hotfixType.HasFlag(HotfixFlagInTool.AdaptByDelegate); |
| | | |
| | | for (int i = 0; i < hotfixBridgesDef.Count; i++) |
| | | { |
| | | MethodDefinition hotfixBridgeDef = hotfixBridgesDef[i]; |
| | |
| | | { |
| | | continue; |
| | | } |
| | | invoke = isTheSameAssembly ? hotfixBridgeDef : getDelegateInvokeFor(method, hotfixBridgeDef, ignoreValueType); |
| | | invoke = (isTheSameAssembly && !isAdaptByDelegate) ? hotfixBridgeDef : getDelegateInvokeFor(method, hotfixBridgeDef, ignoreValueType); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | bool ignoreProperty = hotfixType.HasFlag(HotfixFlagInTool.IgnoreProperty); |
| | | bool ignoreCompilerGenerated = hotfixType.HasFlag(HotfixFlagInTool.IgnoreCompilerGenerated); |
| | | bool ignoreNotPublic = hotfixType.HasFlag(HotfixFlagInTool.IgnoreNotPublic); |
| | | bool isInline = hotfixType.HasFlag(HotfixFlagInTool.Inline); |
| | | bool isIntKey = hotfixType.HasFlag(HotfixFlagInTool.IntKey); |
| | | bool noBaseProxy = hotfixType.HasFlag(HotfixFlagInTool.NoBaseProxy); |
| | | if (ignoreCompilerGenerated && type.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")) |
| | | { |
| | | return true; |
| | | } |
| | | if (isIntKey && type.HasGenericParameters) |
| | | { |
| | | throw new InvalidOperationException(type.FullName + " is generic definition, can not be mark as IntKey!"); |
| | |
| | | { |
| | | continue; |
| | | } |
| | | if (ignoreCompilerGenerated && method.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")) |
| | | { |
| | | continue; |
| | | } |
| | | if (method.Name != ".cctor" && !method.IsAbstract && !method.IsPInvokeImpl && method.Body != null && !method.Name.Contains("<")) |
| | | { |
| | | //Debug.Log(method); |
| | |
| | | } |
| | | } |
| | | |
| | | if (!noBaseProxy) |
| | | { |
| | | List<MethodDefinition> toAdd = new List<MethodDefinition>(); |
| | | foreach (var method in type.Methods) |
| | | { |
| | |
| | | continue; |
| | | } |
| | | if (ignoreProperty && method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))) |
| | | { |
| | | continue; |
| | | } |
| | | if (ignoreCompilerGenerated && method.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")) |
| | | { |
| | | continue; |
| | | } |
| | |
| | | foreach(var md in toAdd) |
| | | { |
| | | type.Methods.Add(md); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | |
| | | |
| | | bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType) |
| | | { |
| | | //如果注入的是xlua所在之外的Assembly的话,不支持该方式 |
| | | if (!isTheSameAssembly) |
| | | { |
| | | return true; |
| | | } |
| | | var type = method.DeclaringType; |
| | | |
| | | bool isFinalize = (method.Name == "Finalize" && method.IsSpecialName); |
| | |
| | | { |
| | | public static class Hotfix |
| | | { |
| | | static bool ContainNotAsciiChar(string s) |
| | | { |
| | | for (int i = 0; i < s.Length; ++i) |
| | | { |
| | | if (s[i] > 127) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | [PostProcessScene] |
| | | [MenuItem("XLua/Hotfix Inject In Editor", false, 3)] |
| | | public static void HotfixInject() |
| | | { |
| | | if (EditorApplication.isCompiling || Application.isPlaying) |
| | | if (Application.isPlaying) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | if (EditorApplication.isCompiling) |
| | | { |
| | | UnityEngine.Debug.LogError("You can't inject before the compilation is done"); |
| | | return; |
| | | } |
| | | |
| | |
| | | foreach (var injectAssemblyPath in injectAssemblyPaths) |
| | | { |
| | | args[1] = injectAssemblyPath.Replace('\\', '/'); |
| | | if (ContainNotAsciiChar(args[1])) |
| | | { |
| | | throw new Exception("project path must contain only ascii characters"); |
| | | } |
| | | |
| | | if (injectAssemblyPaths.Count > 1) |
| | | { |
| | | var injectAssemblyFileName = Path.GetFileName(injectAssemblyPath); |
| | |
| | | hotfix_injection.StartInfo.UseShellExecute = false; |
| | | hotfix_injection.StartInfo.CreateNoWindow = true; |
| | | hotfix_injection.Start(); |
| | | UnityEngine.Debug.Log(hotfix_injection.StandardOutput.ReadToEnd()); |
| | | UnityEngine.Debug.Log(Regex.Replace(hotfix_injection.StandardOutput.ReadToEnd(), @"\s*WARNING: The runtime version supported by this application is unavailable(\s|.)*$", "")); |
| | | hotfix_injection.WaitForExit(); |
| | | } |
| | | |