internal DelegateInvokeObjectArrayThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
internal DelegateInvokeClosedStaticThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
internal DelegateInvokeInstanceClosedOverGenericMethodThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
bool checkProxyMethod(MethodDefinition method, out DelegateInfo info) { info = null; if (!method.IsStatic || method.Body == null) return false; var instrs = method.Body.Instructions; if (instrs.Count < 7) return false; int index = 0; if (instrs[index].OpCode.Code != Code.Ldsfld) return false; var field = instrs[index++].Operand as FieldDefinition; if (field == null || !field.IsStatic) return false; if (!MemberReferenceHelper.compareTypes(method.DeclaringType, field.DeclaringType)) return false; if (!DotNetUtils.isBrtrue(instrs[index++])) return false; if (instrs[index++].OpCode.Code != Code.Ldnull) return false; if (instrs[index].OpCode.Code != Code.Ldftn) return false; var calledMethod = instrs[index++].Operand as MethodReference; if (calledMethod == null) return false; if (instrs[index++].OpCode.Code != Code.Newobj) return false; if (instrs[index].OpCode.Code != Code.Stsfld) return false; if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference)) return false; if (instrs[index].OpCode.Code != Code.Ldsfld) return false; if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference)) return false; for (int i = 0; i < method.Parameters.Count; i++) { if (index >= instrs.Count) return false; if (DotNetUtils.getArgIndex(instrs[index++]) != i) return false; } if (index + 2 > instrs.Count) return false; var call = instrs[index++]; if (call.OpCode.Code != Code.Callvirt) return false; if (instrs[index++].OpCode.Code != Code.Ret) return false; info = new DelegateInfo(field, calledMethod, OpCodes.Call); return true; }
internal DelegateInvokeOpenInstanceThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
internal DelegateInvokeOpenStaticThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
internal DelegateGetThunkMethodOverride(DelegateInfo delegateInfo) { _delegateInfo = delegateInfo; }
public MyInfo(MethodDef method, DelegateInfo delegateInfo) { this.method = method; this.delegateInfo = delegateInfo; }
bool checkProxyMethod(MethodDefinition method, out DelegateInfo info) { info = null; if (!method.IsStatic || method.Body == null) { return(false); } var instrs = method.Body.Instructions; if (instrs.Count < 7) { return(false); } int index = 0; if (instrs[index].OpCode.Code != Code.Ldsfld) { return(false); } var field = instrs[index++].Operand as FieldDefinition; if (field == null || !field.IsStatic) { return(false); } if (!MemberReferenceHelper.compareTypes(method.DeclaringType, field.DeclaringType)) { return(false); } if (!DotNetUtils.isBrtrue(instrs[index++])) { return(false); } if (instrs[index++].OpCode.Code != Code.Ldnull) { return(false); } if (instrs[index].OpCode.Code != Code.Ldftn) { return(false); } var calledMethod = instrs[index++].Operand as MethodReference; if (calledMethod == null) { return(false); } if (instrs[index++].OpCode.Code != Code.Newobj) { return(false); } if (instrs[index].OpCode.Code != Code.Stsfld) { return(false); } if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference)) { return(false); } if (instrs[index].OpCode.Code != Code.Ldsfld) { return(false); } if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference)) { return(false); } for (int i = 0; i < method.Parameters.Count; i++) { if (index >= instrs.Count) { return(false); } if (DotNetUtils.getArgIndex(instrs[index++]) != i) { return(false); } } if (index + 2 > instrs.Count) { return(false); } var call = instrs[index++]; if (call.OpCode.Code != Code.Callvirt) { return(false); } if (instrs[index++].OpCode.Code != Code.Ret) { return(false); } info = new DelegateInfo(field, calledMethod, OpCodes.Call); return(true); }
protected void Page_Load(object sender, EventArgs e) { string action = Request["action"]; string sql = ""; DataTable dt = null; ChouJin cjEnt = null; ShouKuan skEnt = null; ChouJinDetail cjdEnt = null; ChouJinResult cjrEnt = null; string id = Request["id"]; IList <ShouKuan> skEnts = null; IList <ChouJinDetail> cjdEnts = null; IList <ChouJinResult> cjrEnts = null; switch (action) { case "loadyear": sql = "select value as year from NCRL_Portal..SysEnumeration where ParentId='058fbee9-0a9a-4b25-b343-ea8c05396632' order by SortIndex asc"; dt = DataHelper.QueryDataTable(sql); Response.Write("{rows:" + JsonHelper.GetJsonStringFromDataTable(dt) + "}"); Response.End(); break; case "loadmonth": sql = "select value as month from NCRL_Portal..SysEnumeration where ParentId='b25e537b-34e3-4437-87af-692e00facd73' order by SortIndex asc"; dt = DataHelper.QueryDataTable(sql); Response.Write("{rows:" + JsonHelper.GetJsonStringFromDataTable(dt) + "}"); Response.End(); break; case "create": cjEnt = JsonHelper.GetObject <ChouJin>(Request["formdata"]); cjEnt.DoCreate(); Response.Write("{success:true,id:'" + cjEnt.Id + "'}"); Response.End(); break; case "update": cjEnt = JsonHelper.GetObject <ChouJin>(Request["formdata"]); ChouJin originalEnt = ChouJin.Find(cjEnt.Id); EasyDictionary dic = JsonHelper.GetObject <EasyDictionary>(Request["formdata"]); originalEnt = DataHelper.MergeData <ChouJin>(originalEnt, cjEnt, dic.Keys); originalEnt.DoUpdate(); Response.Write("{success:true,id:'" + cjEnt.Id + "'}"); Response.End(); break; case "loadform": cjEnt = ChouJin.Find(id); Response.Write("{success:true,data:" + JsonHelper.GetJsonString(cjEnt) + "}"); Response.End(); break; case "loadshoukuan": skEnts = ShouKuan.FindAllByProperty(ShouKuan.Prop_ShouKuanDate, ShouKuan.Prop_ChouJinId, id); if (skEnts.Count == 0) { cjEnt = ChouJin.Find(id); sql = @"select a.Id,a.ProjectId,a.InvoiceId,a.ShouKuanAmount,a.ShouKuanDate,a.ShiJiShouFei, a.YiFenPercent,a.ChouJinAmount,b.ProjectName,c.InvoiceNo from NCRL_SP..ShouKuan a left join NCRL_SP..Project b on a.ProjectId=b.Id left join NCRL_SP..Invoice c on a.InvoiceId=c.Id where YiFenPercent is null and year(ShouKuanDate)='" + cjEnt.BelongYear + "' and month(ShouKuanDate)='" + (Convert.ToInt32(cjEnt.BelongMonth) - 1) + "' and isnull(a.Status,'')<>'已作废' order by ShouKuanDate asc"; } else { sql = @"select a.Id,a.ProjectId,a.InvoiceId,a.ShouKuanAmount,a.ShouKuanDate,a.ShiJiShouFei, a.YiFenPercent,a.ChouJinAmount,b.ProjectName,c.InvoiceNo from NCRL_SP..ShouKuan a left join NCRL_SP..Project b on a.ProjectId=b.Id left join NCRL_SP..Invoice c on a.InvoiceId=c.Id where ChouJinId='" + id + "' order by a.ShouKuanDate asc"; } dt = DataHelper.QueryDataTable(sql); Response.Write("{rows:" + JsonHelper.GetJsonStringFromDataTable(dt) + "}"); Response.End(); break; case "updateshoukuan": string shoukuanids = Request["shoukuanids"]; string[] idarray = shoukuanids.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string str in idarray) { skEnt = ShouKuan.Find(str); skEnt.ChouJinId = id; skEnt.DoUpdate(); } //顺便把酬金分配明细的store构建后送到前端 为动态页面的生成提供数据基础 skEnts = ShouKuan.FindAllByProperty(ShouKuan.Prop_ShouKuanDate, ShouKuan.Prop_ChouJinId, id); DataTable dt2 = new DataTable(); //构建表格列 // dc = new DataColumn("MajorName"); //dt2.Columns.Add(dc); DataColumn dc = new DataColumn("UserId"); dt2.Columns.Add(dc); dc = new DataColumn("UserName"); dt2.Columns.Add(dc); dc = new DataColumn("StageAmount"); dt2.Columns.Add(dc); foreach (ShouKuan tempEnt in skEnts) { dc = new DataColumn(tempEnt.Id + "@A"); dt2.Columns.Add(dc); dc = new DataColumn(tempEnt.Id + "@B"); dt2.Columns.Add(dc); dc = new DataColumn(tempEnt.Id + "@C"); dt2.Columns.Add(dc); } //构建表格行 先构建前面的特殊5行 DataRow dr1 = dt2.NewRow(); DataRow dr2 = dt2.NewRow(); DataRow dr3 = dt2.NewRow(); DataRow dr4 = dt2.NewRow(); DataRow dr5 = dt2.NewRow(); Project pEnt = null; dr1["UserName"] = "******"; dr2["UserName"] = "******"; dr3["UserName"] = "******"; dr4["UserName"] = "******"; dr5["UserName"] = "******"; foreach (ShouKuan tempEnt in skEnts) { pEnt = Project.Find(tempEnt.ProjectId); dr1[tempEnt.Id + "@A"] = pEnt.ProjectName; dr1[tempEnt.Id + "@C"] = tempEnt.ShouKuanAmount; //获取收款金额 if (!string.IsNullOrEmpty(pEnt.DelegateInfoId)) { dr2[tempEnt.Id + "@A"] = DelegateInfo.Find(pEnt.DelegateInfoId).DelegateName; //第二行收款记录第一列显示窗口名称 第三列显示窗口比例 } dr2[tempEnt.Id + "@B"] = tempEnt.Id; dr2[tempEnt.Id + "@C"] = pEnt.ChuangKouBiLi; //将收款记录的ID存到第二行的第三列上。便于前台获取 dr3[tempEnt.Id + "@C"] = tempEnt.ShiJiShouFei; //第三行收款记录第三列存显示实际收费 即收款金额-收款金额*窗口比例 dr4[tempEnt.Id + "@C"] = tempEnt.ChouJinAmount; dr5[tempEnt.Id + "@A"] = tempEnt.YiFenPercent; dr5[tempEnt.Id + "@B"] = 100; } dt2.Rows.Add(dr1); dt2.Rows.Add(dr2); dt2.Rows.Add(dr3); dt2.Rows.Add(dr4); dt2.Rows.Add(dr5); //所有的专家 IList <Expert> expEnts = Expert.FindAllByProperty(Expert.Prop_SortIndex, Expert.Prop_Status, "T"); foreach (Expert tEnt in expEnts) { DataRow dr = dt2.NewRow(); dr["UserId"] = tEnt.Id; dr["UserName"] = tEnt.UserName; cjrEnts = ChouJinResult.FindAllByProperties(ChouJinResult.Prop_ChouJinId, id, ChouJinResult.Prop_ExpertId, tEnt.Id); dr["StageAmount"] = cjrEnts.Count == 0 ? "" : cjrEnts[0].StageAmount + ""; foreach (ShouKuan shoukuanEnt in skEnts) { cjdEnts = ChouJinDetail.FindAllByProperties(ChouJinDetail.Prop_ChouJinId, id, ChouJinDetail.Prop_ExpertId, tEnt.Id, ChouJinDetail.Prop_ShouKuanId, shoukuanEnt.Id); IList <ProjectUser> puEnts = ProjectUser.FindAllByProperties(ProjectUser.Prop_ProjectId, shoukuanEnt.ProjectId, ProjectUser.Prop_UserId, tEnt.Id); dr[shoukuanEnt.Id + "@A"] = puEnts.Count > 0 ? "√" : ""; dr[shoukuanEnt.Id + "@B"] = cjdEnts.Count > 0 ? cjdEnts[0].ChouJinPercent : null; dr[shoukuanEnt.Id + "@C"] = cjdEnts.Count > 0 ? cjdEnts[0].ChouJinAmount : null; } dt2.Rows.Add(dr); } Response.Write("{success:true,rows:" + JsonHelper.GetJsonStringFromDataTable(dt2) + "}"); Response.End(); break; case "savechoujindetail": cjdEnts = ChouJinDetail.FindAllByProperties(ChouJinDetail.Prop_ChouJinId, id, ChouJinDetail.Prop_ExpertId, Request["expertid"], ChouJinDetail.Prop_ShouKuanId, Request["shoukuanid"]); if (cjdEnts.Count == 0) { if (Convert.ToDecimal(Request["choujinpercent"]) > 0) { cjdEnt = new ChouJinDetail(); cjdEnt.ChouJinId = id; cjdEnt.ExpertId = Request["expertid"]; cjdEnt.UserName = Request["username"]; cjdEnt.ShouKuanId = Request["shoukuanid"]; cjdEnt.ChouJinPercent = Convert.ToDecimal(Request["choujinpercent"]); cjdEnt.ChouJinAmount = Convert.ToDecimal(Request["choujinamount"]); cjdEnt.IfCanYu = Request["ifcanyu"]; cjdEnt.DoCreate(); //酬金明细保存后,同时更新酬金结果 、收款记录的已分百分比 skEnt = ShouKuan.Find(Request["shoukuanid"]); skEnt.YiFenPercent = Convert.ToDecimal(Request["yifenpercent"]); skEnt.DoUpdate(); } } else { if (Convert.ToDecimal(Request["choujinpercent"]) > 0) { cjdEnt = cjdEnts[0]; cjdEnt.ChouJinPercent = Convert.ToDecimal(Request["choujinpercent"]); cjdEnt.ChouJinAmount = Convert.ToDecimal(Request["choujinamount"]); cjdEnt.IfCanYu = Request["ifcanyu"]; cjdEnt.DoUpdate(); skEnt = ShouKuan.Find(Request["shoukuanid"]); skEnt.YiFenPercent = Convert.ToDecimal(Request["yifenpercent"]); skEnt.DoUpdate(); } else { cjdEnts[0].DoDelete(); } } cjrEnts = ChouJinResult.FindAllByProperties(ChouJinResult.Prop_ExpertId, Request["expertid"], ChouJinResult.Prop_ChouJinId, id); if (cjrEnts.Count == 0) { cjrEnt = new ChouJinResult(); cjrEnt.ExpertId = Request["expertid"]; cjrEnt.UserName = Request["username"]; cjrEnt.ChouJinId = id; cjrEnt.StageAmount = Convert.ToDecimal(Request["stageamount"]); cjrEnt.DoCreate(); } else { if (Convert.ToDecimal(Request["stageamount"]) > 0) { cjrEnt = cjrEnts[0]; cjrEnt.StageAmount = Convert.ToDecimal(Request["stageamount"]); cjrEnt.DoUpdate(); } else { cjrEnts[0].DoDelete(); } } break; case "loadchoujinresult": //默认调整金额==分配金额 sql = @"select a.Id as ExpertId,a.UserName,b.Remark,b.StageAmount,isnull(AdjustAmount,StageAmount) AdjustAmount from NCRL_SP..Expert a left join (select * from NCRL_SP..ChouJinResult where ChouJinId='{0}') b on a.Id=b.ExpertId"; sql = string.Format(sql, id); dt = DataHelper.QueryDataTable(sql); cjEnt = ChouJin.Find(id); Response.Write("{rows:" + JsonHelper.GetJsonStringFromDataTable(dt) + ",title:'" + cjEnt.BelongYear + "年" + cjEnt.BelongMonth + "月专家酬金'}"); Response.End(); break; case "adjustresult": cjrEnts = ChouJinResult.FindAllByProperties(ChouJinResult.Prop_ChouJinId, id, ChouJinResult.Prop_ExpertId, Request["expertid"]); if (cjrEnts.Count == 0) { cjrEnt = new ChouJinResult(); cjrEnt.ExpertId = Request["expertid"]; cjrEnt.UserName = Request["username"]; cjrEnt.ChouJinId = id; cjrEnt.AdjustAmount = Convert.ToDecimal(Request["adjustamount"]); cjrEnt.Remark = Request["remark"]; cjrEnt.DoCreate(); } else { cjrEnt = cjrEnts[0]; cjrEnt.AdjustAmount = Convert.ToDecimal(Request["adjustamount"]); cjrEnt.Remark = Request["remark"]; cjrEnt.DoUpdate(); } break; case "loadshoukuan_unfenpei": sql = @"select a.Id,a.ProjectId,a.InvoiceId,a.ShouKuanAmount,a.ShouKuanDate,a.ShiJiShouFei, a.YiFenPercent,a.ChouJinAmount,b.ProjectName,c.InvoiceNo from NCRL_SP..ShouKuan a left join NCRL_SP..Project b on a.ProjectId=b.Id left join NCRL_SP..Invoice c on a.InvoiceId=c.Id where isnull(ChouJinId,'')='' order by a.ShouKuanDate asc"; dt = DataHelper.QueryDataTable(sql); Response.Write("{rows:" + JsonHelper.GetJsonStringFromDataTable(dt) + "}"); Response.End(); break; } }
/// <summary> /// Verifies that the delegate signature provided in dst can be dynamically mapped to /// the method provided by src, with the possible addition of optional parameters set /// to their default values. /// </summary> /// <param name="expected">The method return type and parameter types expected.</param> /// <param name="actual">The method to be called.</param> /// <returns>The parameters used in the call to the actual method.</returns> /// <exception cref="DetourException">If the delegate does not match the target.</exception> private static ParameterInfo[] ValidateDelegate(DelegateInfo expected, MethodInfo actual) { var parameterTypes = expected.ParameterTypes; var returnType = expected.ReturnType; // Validate return types if (!returnType.IsAssignableFrom(actual.ReturnType)) { throw new DetourException("Return type {0} cannot be converted to type {1}". F(actual.ReturnType.FullName, returnType.FullName)); } // Do not allow methods declared in not yet closed generic types var baseType = actual.DeclaringType; if (baseType.ContainsGenericParameters) { throw new DetourException(("Method parent type {0} must have all " + "generic parameters defined").F(baseType.FullName)); } // Validate parameter types string actualName = baseType.FullName + "." + actual.Name; var actualParams = actual.GetParameters(); int n = actualParams.Length, check = parameterTypes.Length; Type[] actualParamTypes, currentTypes = new Type[n]; for (int i = 0; i < n; i++) { currentTypes[i] = actualParams[i].ParameterType; } if (actual.IsStatic) { actualParamTypes = currentTypes; } else { actualParamTypes = PTranspilerTools.PushDeclaringType(currentTypes, baseType); n++; } if (check > n) { throw new DetourException(("Method {0} has only {1:D} parameters, but " + "{2:D} were supplied").F(actual.ToString(), n, check)); } // Check up to the number we have for (int i = 0; i < check; i++) { Type have = actualParamTypes[i], want = parameterTypes[i]; if (!have.IsAssignableFrom(want)) { throw new DetourException(("Argument {0:D} for method {3} cannot be " + "converted from {1} to {2}").F(i, have.FullName, want.FullName, actualName)); } } // Any remaining parameters must be optional int offset = actual.IsStatic ? 0 : 1; for (int i = check; i < n; i++) { var cParam = actualParams[i - offset]; if (!cParam.IsOptional) { throw new DetourException(("New argument {0:D} for method {1} ({2}) " + "is not optional").F(i, actualName, cParam.ParameterType.FullName)); } } return(actualParams); }
/// <summary> /// Creates a dynamic detour method of the specified delegate type to wrap a base game /// method with the specified name. The dynamic method will automatically adapt if /// optional parameters are added, filling in their default values. /// </summary> /// <typeparam name="D">The delegate type to be used to call the detour.</typeparam> /// <param name="target">The target method to be called.</param> /// <returns>The detour that will call that method.</returns> /// <exception cref="DetourException">If the delegate does not match the target.</exception> public static D Detour <D>(this MethodInfo target) where D : Delegate { if (target == null) { throw new ArgumentNullException("target"); } if (target.ContainsGenericParameters) { throw new ArgumentException("Generic types must have all parameters defined"); } var expected = DelegateInfo.Create(typeof(D)); var parentType = target.DeclaringType; var expectedParamTypes = expected.ParameterTypes; var actualParams = ValidateDelegate(expected, target); int offset = target.IsStatic ? 0 : 1; // Method will be "declared" in the type of the target, as we are detouring around // a method of that type var caller = new DynamicMethod(target.Name + "_Detour", expected.ReturnType, expectedParamTypes, parentType, true); var generator = caller.GetILGenerator(); // Load the known method arguments onto the stack int n = expectedParamTypes.Length, need = actualParams.Length + offset; if (n > 0) { generator.Emit(OpCodes.Ldarg_0); } if (n > 1) { generator.Emit(OpCodes.Ldarg_1); } if (n > 2) { generator.Emit(OpCodes.Ldarg_2); } if (n > 3) { generator.Emit(OpCodes.Ldarg_3); } for (int i = 4; i < n; i++) { generator.Emit(OpCodes.Ldarg_S, i); } // Load the rest as defaults for (int i = n; i < need; i++) { var param = actualParams[i - offset]; PTranspilerTools.GenerateDefaultLoad(generator, param.ParameterType, param. DefaultValue); } if (parentType.IsValueType || target.IsStatic) { generator.Emit(OpCodes.Call, target); } else { generator.Emit(OpCodes.Callvirt, target); } generator.Emit(OpCodes.Ret); // Define the parameter names, parameter indexes start at 1 if (offset > 0) { caller.DefineParameter(1, ParameterAttributes.None, "this"); } for (int i = offset; i < n; i++) { var oldParam = actualParams[i - offset]; caller.DefineParameter(i + 1, oldParam.Attributes, oldParam.Name); } #if DEBUG PUtil.LogDebug("Created delegate {0} for method {1}.{2} with parameters [{3}]". F(caller.Name, parentType.FullName, target.Name, actualParams.Join(","))); #endif return(caller.CreateDelegate(typeof(D)) as D); }
/// <summary> /// Компилируем делегат /// </summary> private static void CompileDelegate <T>(String name, DelegateInfo <T> del) { // перечисляем все библиотеки, от которых может зависеть текст функции String[] referenceAssemblies = { "System.dll", "System.Data.dll", "System.Design.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "System.Xml.dll" }; String className = "C" + name + m_classIndex.ToString(); m_classIndex++; // создаем полный текст класса с функцией StringBuilder sb = new StringBuilder(); sb.AppendLine("using System;"); sb.AppendLine("using System.Data;"); sb.AppendLine("using System.Text;"); sb.AppendLine("using System.Design;"); sb.AppendLine("using System.Drawing;"); sb.AppendLine("using System.Windows.Forms;"); sb.AppendLine("using System.Collections.Generic;"); sb.AppendLine("namespace DelegateGenerator"); sb.AppendLine("{"); sb.Append(" public class "); sb.AppendLine(className); sb.AppendLine(" {"); sb.AppendLine(del.Code); sb.AppendLine(" }"); sb.AppendLine("}"); // компилируем класс CompilerParameters codeParams = new CompilerParameters(referenceAssemblies); codeParams.GenerateExecutable = false; codeParams.GenerateInMemory = true; CSharpCodeProvider codeProvider = new CSharpCodeProvider(); CompilerResults codeResult = codeProvider.CompileAssemblyFromSource(codeParams, sb.ToString()); // проверяем результат на ошибку if (codeResult.Errors.HasErrors) { StringBuilder err = new StringBuilder(); for (int i = 0; i < codeResult.Errors.Count; ++i) { err.AppendLine(codeResult.Errors[i].ToString()); } del.ErrorText = err.ToString(); return; } // получаем функцию созданного класса по имени Type type = codeResult.CompiledAssembly.GetType("DelegateGenerator." + className); del.MethodInfo = type.GetMethod(name); if (null == del.MethodInfo) { del.ErrorText = String.Format("Delegate name '{0}' error", name); } else { del.Delegate = Delegate.CreateDelegate(typeof(T), del.MethodInfo); if (null == del.Delegate) { del.ErrorText = String.Format("Delegate type '{0}' error", name); } } }
bool checkProxyMethod(MethodDef method, out DelegateInfo info) { info = null; if (!method.IsStatic || method.Body == null) { return(false); } var instrs = method.Body.Instructions; if (instrs.Count < 7) { return(false); } int index = 0; if (instrs[index].OpCode.Code != Code.Ldsfld) { return(false); } var field = instrs[index++].Operand as FieldDef; if (field == null || !field.IsStatic) { return(false); } if (!new SigComparer().Equals(method.DeclaringType, field.DeclaringType)) { return(false); } if (!instrs[index++].IsBrtrue()) { return(false); } if (instrs[index++].OpCode.Code != Code.Ldnull) { return(false); } if (instrs[index].OpCode.Code != Code.Ldftn) { return(false); } var calledMethod = instrs[index++].Operand as IMethod; if (calledMethod == null) { return(false); } if (instrs[index++].OpCode.Code != Code.Newobj) { return(false); } if (instrs[index].OpCode.Code != Code.Stsfld) { return(false); } if (!new SigComparer().Equals(field, instrs[index++].Operand as IField)) { return(false); } if (instrs[index].OpCode.Code != Code.Ldsfld) { return(false); } if (!new SigComparer().Equals(field, instrs[index++].Operand as IField)) { return(false); } var sig = method.MethodSig; if (sig == null) { return(false); } for (int i = 0; i < sig.Params.Count; i++) { if (index >= instrs.Count) { return(false); } if (instrs[index++].GetParameterIndex() != i) { return(false); } } if (index + 2 > instrs.Count) { return(false); } var call = instrs[index++]; if (call.OpCode.Code != Code.Callvirt) { return(false); } if (instrs[index++].OpCode.Code != Code.Ret) { return(false); } info = new DelegateInfo(field, calledMethod, OpCodes.Call); return(true); }
void add(Dictionary<Block, List<RemoveInfo>> removeInfos, Block block, int index, DelegateInfo di) { List<RemoveInfo> list; if (!removeInfos.TryGetValue(block, out list)) removeInfos[block] = list = new List<RemoveInfo>(); list.Add(new RemoveInfo { Index = index, DelegateInfo = di, }); }
protected void add(MethodDefinition method, DelegateInfo di) { proxyMethodToDelegateInfo.add(method, di); }
public DelegateThunk(DelegateInfo delegateInfo) { _delegateInfo = delegateInfo; }
protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: { TypeDesc target = (TypeDesc)Target; encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewObjectHelperForType(target))); } break; case ReadyToRunHelperId.VirtualCall: if (relocsOnly) { break; } AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr); { int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, (MethodDesc)Target); Debug.Assert(slot != -1); AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize), 0, AddrModeSize.Int64); encoder.EmitJmpToAddrMode(ref jmpAddrMode); } break; case ReadyToRunHelperId.IsInstanceOf: { TypeDesc target = (TypeDesc)Target; encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false))); } break; case ReadyToRunHelperId.CastClass: { TypeDesc target = (TypeDesc)Target; encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true))); } break; case ReadyToRunHelperId.NewArr1: { TypeDesc target = (TypeDesc)Target; // TODO: Swap argument order instead // mov arg1, arg0 encoder.Builder.EmitByte(0x48); encoder.Builder.EmitShort((short)((encoder.TargetRegister.Arg0 == Register.RCX) ? 0xD18B : 0xF78B)); encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.NecessaryTypeSymbol(target)); encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target))); } break; case ReadyToRunHelperId.GetNonGCStaticBase: { MetadataType target = (MetadataType)Target; if (!target.HasStaticConstructor) { Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase); encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target)); encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } break; case ReadyToRunHelperId.GetThreadStaticBase: encoder.EmitINT3(); break; case ReadyToRunHelperId.GetGCStaticBase: { MetadataType target = (MetadataType)Target; if (!target.HasStaticConstructor) { encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target)); encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol(target)); AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx); encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } break; case ReadyToRunHelperId.DelegateCtor: { DelegateInfo target = (DelegateInfo)Target; encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.MethodEntrypoint(target.Target)); if (target.ShuffleThunk != null) { encoder.EmitLEAQ(encoder.TargetRegister.Arg3, factory.MethodEntrypoint(target.ShuffleThunk)); } encoder.EmitJMP(factory.MethodEntrypoint(target.Ctor)); } break; default: throw new NotImplementedException(); } }
public void find() { if (delegateCreatorMethods.Count == 0) return; Log.v("Finding all proxy delegates"); foreach (var type in module.Types) { if (type.BaseType == null || type.BaseType.FullName != "System.MulticastDelegate") continue; var cctor = findMethod(type, ".cctor"); if (cctor == null || !cctor.HasBody) continue; if (!type.HasFields) continue; object context = checkCctor(type, cctor); if (context == null) continue; Log.v("Found proxy delegate: {0} ({1:X8})", type, type.MetadataToken.ToUInt32()); RemovedDelegateCreatorCalls++; onFoundProxyDelegate(type); Log.indent(); foreach (var field in type.Fields) { if (!field.IsStatic || field.IsPublic) continue; MethodReference calledMethod; OpCode callOpcode; getCallInfo(context, field, out calledMethod, out callOpcode); if (calledMethod == null) throw new ApplicationException("calledMethod is null"); fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, calledMethod, callOpcode); Log.v("Field: {0}, Opcode: {1}, Method: {2} ({3:X8})", field.Name, callOpcode, calledMethod, calledMethod.MetadataToken.ToUInt32()); } Log.deIndent(); delegateTypesDict[type] = true; } }
protected static void Add(Dictionary <Block, List <RemoveInfo> > removeInfos, Block block, int index, DelegateInfo di) { List <RemoveInfo> list; if (!removeInfos.TryGetValue(block, out list)) { removeInfos[block] = list = new List <RemoveInfo>(); } list.Add(new RemoveInfo { Index = index, DelegateInfo = di, }); }
protected void AddDelegateInfo(DelegateInfo di) { fieldToDelegateInfo.Add(di.field, di); }
protected virtual BlockInstr FindProxyCall(DelegateInfo di, Block block, int index) { return(FindProxyCall(di, block, index, new Dictionary <Block, bool>(), 1)); }
internal DelegateInvokeMulticastThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
BlockInstr FindProxyCall(DelegateInfo di, Block block, int index, Dictionary <Block, bool> visited, int stack) { if (visited.ContainsKey(block)) { return(null); } if (index <= 0) { visited[block] = true; } var instrs = block.Instructions; for (int i = index + 1; i < instrs.Count; i++) { if (stack <= 0) { return(null); } var instr = instrs[i]; instr.Instruction.UpdateStack(ref stack, false); if (stack < 0) { return(null); } if (instr.OpCode != OpCodes.Call && instr.OpCode != OpCodes.Callvirt) { if (stack <= 0) { return(null); } continue; } var calledMethod = instr.Operand as IMethod; if (calledMethod == null) { return(null); } if (stack != (DotNetUtils.HasReturnValue(calledMethod) ? 1 : 0)) { continue; } if (calledMethod.Name != "Invoke") { return(null); } return(new BlockInstr { Block = block, Index = i, }); } if (stack <= 0) { return(null); } foreach (var target in block.GetTargets()) { var info = FindProxyCall(di, target, -1, visited, stack); if (info != null) { return(info); } } return(null); }
internal DelegateReversePInvokeThunk(DelegateInfo delegateInfo) : base(delegateInfo) { }
protected void Add(MethodDef method, DelegateInfo di) { proxyMethodToDelegateInfo.Add(method, di); }
public DelegateDynamicInvokeThunk(DelegateInfo delegateInfo) { _delegateInfo = delegateInfo; }
public void find() { if (delegateCreatorMethod == null) return; Log.v("Finding all proxy delegates"); foreach (var type in module.Types) { if (type.BaseType == null || type.BaseType.FullName != "System.MulticastDelegate") continue; var cctor = findMethod(type, ".cctor"); if (cctor == null || !cctor.HasBody) continue; if (!type.HasFields) continue; var instrs = cctor.Body.Instructions; if (instrs.Count != 3) continue; if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code)) continue; if (instrs[1].OpCode != OpCodes.Call || instrs[1].Operand != delegateCreatorMethod) continue; if (instrs[2].OpCode != OpCodes.Ret) continue; int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]); if (type.MetadataToken.ToInt32() != delegateToken) { Log.w("Delegate token is not current type"); continue; } Log.v("Found proxy delegate: {0} ({1:X8})", type, type.MetadataToken.ToUInt32()); RemovedDelegateCreatorCalls++; Log.indent(); foreach (var field in type.Fields) { if (!field.IsStatic || field.IsPublic) continue; int methodIndex; bool isVirtual; getCallInfo(field, out methodIndex, out isVirtual); if (methodIndex >= memberReferences.Count) throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count)); var methodRef = memberReferences[methodIndex] as MethodReference; if (methodRef == null) throw new ApplicationException("methodRef is null"); fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, methodRef, isVirtual); Log.v("Field: {0}, Virtual: {1}, Method: {2}, RID: {3}", field.Name, isVirtual, methodRef, methodIndex + 1); } Log.deIndent(); delegateTypesDict[type] = true; } }
protected void addDelegateInfo(DelegateInfo di) { fieldToDelegateInfo.add(di.field, di); }
BlockInstr findProxyCall(DelegateInfo di, Block block, int index, Dictionary<Block, bool> visited, int stack) { if (visited.ContainsKey(block)) return null; if (index <= 0) visited[block] = true; var instrs = block.Instructions; for (int i = index + 1; i < instrs.Count; i++) { if (stack <= 0) return null; var instr = instrs[i]; DotNetUtils.updateStack(instr.Instruction, ref stack, false); if (stack < 0) return null; if (instr.OpCode != OpCodes.Call && instr.OpCode != OpCodes.Callvirt) continue; var method = DotNetUtils.getMethod(module, instr.Operand as MethodReference); if (method == null) continue; if (stack != (DotNetUtils.hasReturnValue(method) ? 1 : 0)) continue; if (method.DeclaringType != di.field.DeclaringType) continue; return new BlockInstr { Block = block, Index = i, }; } if (stack <= 0) return null; foreach (var target in block.getTargets()) { var info = findProxyCall(di, target, -1, visited, stack); if (info != null) return info; } return null; }
private void CreateAndAssignNewDelegate(DelegateInfo delInfo) { var method = delInfo.Method; var target = delInfo.Target; var pTypes = method.GetParameters().Select(x => x.ParameterType).ToArray(); var args = new object[pTypes.Length]; Type delegateType = null; if (method.ReturnType == typeof(void)) { if (args.Length == 0) { delegateType = typeof(Action); } else if (args.Length == 1) { delegateType = typeof(Action <>).MakeGenericType(pTypes); } else if (args.Length == 2) { delegateType = typeof(Action <,>).MakeGenericType(pTypes); } else if (args.Length == 3) { delegateType = typeof(Action <, ,>).MakeGenericType(pTypes); } else if (args.Length == 4) { delegateType = typeof(Action <, , ,>).MakeGenericType(pTypes); } else if (args.Length == 5) { delegateType = typeof(Action <, , , ,>).MakeGenericType(pTypes); } } else { pTypes = pTypes.Append(method.ReturnType).ToArray(); if (args.Length == 0) { delegateType = typeof(Func <>).MakeArrayType(); } else if (args.Length == 1) { delegateType = typeof(Func <,>).MakeGenericType(pTypes); } else if (args.Length == 2) { delegateType = typeof(Func <, ,>).MakeGenericType(pTypes); } else if (args.Length == 3) { delegateType = typeof(Func <, , ,>).MakeGenericType(pTypes); } else if (args.Length == 4) { delegateType = typeof(Func <, , , ,>).MakeGenericType(pTypes); } else if (args.Length == 5) { delegateType = typeof(Func <, , , , ,>).MakeGenericType(pTypes); } } if (delegateType == null) { Debug.LogError("Unsupported Method Type"); return; } var del = Delegate.CreateDelegate(delegateType, target, method); this.Property.Tree.DelayActionUntilRepaint(() => { this.ValueEntry.WeakSmartValue = new BetterEventEntry(del); GUI.changed = true; this.Property.RefreshSetup(); }); }
bool CheckProxyMethod(MethodDef method, out DelegateInfo info) { info = null; if (!method.IsStatic || method.Body == null) return false; var instrs = method.Body.Instructions; if (instrs.Count < 7) return false; int index = 0; if (instrs[index].OpCode.Code != Code.Ldsfld) return false; var field = instrs[index++].Operand as FieldDef; if (field == null || !field.IsStatic) return false; if (!new SigComparer().Equals(method.DeclaringType, field.DeclaringType)) return false; if (!instrs[index++].IsBrtrue()) return false; if (instrs[index++].OpCode.Code != Code.Ldnull) return false; if (instrs[index].OpCode.Code != Code.Ldftn) return false; var calledMethod = instrs[index++].Operand as IMethod; if (calledMethod == null) return false; if (instrs[index++].OpCode.Code != Code.Newobj) return false; if (instrs[index].OpCode.Code != Code.Stsfld) return false; if (!new SigComparer().Equals(field, instrs[index++].Operand as IField)) return false; if (instrs[index].OpCode.Code != Code.Ldsfld) return false; if (!new SigComparer().Equals(field, instrs[index++].Operand as IField)) return false; var sig = method.MethodSig; if (sig == null) return false; for (int i = 0; i < sig.Params.Count; i++) { if (index >= instrs.Count) return false; if (instrs[index++].GetParameterIndex() != i) return false; } if (index + 2 > instrs.Count) return false; var call = instrs[index++]; if (call.OpCode.Code != Code.Callvirt) return false; if (instrs[index++].OpCode.Code != Code.Ret) return false; info = new DelegateInfo(field, calledMethod, OpCodes.Call); return true; }
public MyInfo(MethodDefinition method, DelegateInfo delegateInfo) { this.method = method; this.delegateInfo = delegateInfo; }
public DelegateInfo GetDelegateCtor(MethodDesc target) { DelegateInfo info; if (!_delegateInfos.TryGetValue(target, out info)) { _delegateInfos.Add(target, info = new DelegateInfo(this, target)); } return info; }
protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly) { switch (Id) { case ReadyToRunHelperId.NewHelper: encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol((TypeDesc)Target)); encoder.EmitJMP(factory.ExternSymbol("__allocate_object")); break; case ReadyToRunHelperId.VirtualCall: if (relocsOnly) { break; } AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr); { int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, (MethodDesc)Target); Debug.Assert(slot != -1); AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize), 0, AddrModeSize.Int64); encoder.EmitJmpToAddrMode(ref jmpAddrMode); } break; case ReadyToRunHelperId.IsInstanceOf: encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target)); encoder.EmitJMP(factory.ExternSymbol("__isinst_class")); break; case ReadyToRunHelperId.CastClass: encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target)); encoder.EmitJMP(factory.ExternSymbol("__castclass_class")); break; case ReadyToRunHelperId.NewArr1: encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target)); encoder.EmitJMP(factory.ExternSymbol("__allocate_array")); break; case ReadyToRunHelperId.GetNonGCStaticBase: if (!((MetadataType)Target).HasStaticConstructor) { Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase); encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol((MetadataType)Target)); encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target)); encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol((MetadataType)Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } break; case ReadyToRunHelperId.GetThreadStaticBase: encoder.EmitINT3(); break; case ReadyToRunHelperId.GetGCStaticBase: if (!((MetadataType)Target).HasStaticConstructor) { encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol((MetadataType)Target)); AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); encoder.EmitRET(); } else { // We need to trigger the cctor before returning the base encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target)); encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol((MetadataType)Target)); AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64); encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx); encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } break; case ReadyToRunHelperId.DelegateCtor: { DelegateInfo target = (DelegateInfo)Target; encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.MethodEntrypoint(target.Target)); if (target.ShuffleThunk != null) { encoder.EmitLEAQ(encoder.TargetRegister.Arg3, factory.MethodEntrypoint(target.ShuffleThunk)); } encoder.EmitJMP(factory.MethodEntrypoint(target.Ctor)); } break; default: throw new NotImplementedException(); } }