17,740
社区成员
发帖
与我相关
我的任务
分享
public static string DoWebService(string url, string commandname, object[] args, string bindingname, string ns, string parmnames, bool returnxml, bool useaction)
{
string rt = "";
AssemblyBuilder AB = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("WebService"), AssemblyBuilderAccess.RunAndSave);
TypeBuilder T = AB.DefineDynamicModule("WebService", "WebService.dll")
.DefineType("Nordasoft.WebService", TypeAttributes.Public, typeof(System.Web.Services.Protocols.SoapHttpClientProtocol));
T.SetCustomAttribute(
new CustomAttributeBuilder(
typeof(WebServiceBindingAttribute).GetConstructor(new Type[] { typeof(string), typeof(string) }),
new object[] { bindingname, ns }));
List<Type> TS = new List<Type>();
string[] pns = parmnames.Split(",".ToCharArray());
for (int i = 0; i < args.Length; i++)
{
if (pns[i].StartsWith("#"))
{
TS.Add(args[i].GetType().MakeByRefType());
}
else
{
TS.Add(args[i].GetType());
}
}
Type[] PTS = TS.ToArray();
MethodBuilder MB = T.DefineMethod(commandname, MethodAttributes.Public, typeof(string), PTS);
string actions = "";
if (useaction)
{
actions = ns + commandname;
}
MB.SetCustomAttribute(
new CustomAttributeBuilder(
typeof(SoapDocumentMethodAttribute).GetConstructor(new Type[] { typeof(string) }),
new object[] { actions }));
ParameterBuilder pb;
int outstart = PTS.Length;
if (PTS.Length > 0)
{
for (int pi = 1; pi <= PTS.Length; pi++)
{
if (pns[pi - 1].StartsWith("#"))
{
if (outstart == PTS.Length) outstart = pi - 1;
pb = MB.DefineParameter(pi, ParameterAttributes.Out, pns[pi - 1].Substring(1));
}
else
{
pb = MB.DefineParameter(pi, ParameterAttributes.None, pns[pi - 1]);
}
}
}
if (returnxml)
{
pb = MB.DefineParameter(0, ParameterAttributes.None, null);
pb.SetCustomAttribute(
new CustomAttributeBuilder(
typeof(System.Xml.Serialization.XmlElementAttribute).GetConstructor(new Type[] { typeof(string) }),
new object[] { "return" },
new PropertyInfo[] { typeof(System.Xml.Serialization.XmlElementAttribute).GetProperty("Form"), },
new object[] { System.Xml.Schema.XmlSchemaForm.Unqualified }
)
);
}
ILGenerator ig = MB.GetILGenerator();
//声明命令名字符串
ig.DeclareLocal(typeof(string));
//声明命令参数数组
ig.DeclareLocal(typeof(object[]));
ig.DeclareLocal(typeof(object[]));
//加载参数0到堆栈[0]==参数0表示当前方法
ig.Emit(OpCodes.Ldarg_0);
//加载字符串到堆栈[1]
ig.Emit(OpCodes.Ldstr, commandname);
//把参数数量加到堆栈[2]
ig.Emit(OpCodes.Ldc_I4, outstart);
//用堆栈[2]的数字生成object数组并放如堆栈[2]
ig.Emit(OpCodes.Newarr, typeof(object));
//把堆栈[2]的数组付给参数[1]==声明的数组
ig.Emit(OpCodes.Stloc_1);
//将数组放回堆栈[2]
ig.Emit(OpCodes.Ldloc_1);
//循环将参数放到数组对应的位置
for (int pi = 0; pi < outstart; pi++)
{
//将参数序号加到堆栈
ig.Emit(OpCodes.Ldc_I4, pi);
//将参数[序号+1]位置的数据加到堆栈
ig.Emit(OpCodes.Ldarg, pi + 1);
//将[序号+1]对应的数据替换到声明数组[序号]位置
ig.Emit(OpCodes.Stelem_Ref);
//将参数1入栈
ig.Emit(OpCodes.Ldloc_1);
}
//调用基类型Invoke方法
MethodInfo cm = T.BaseType.GetMethod("Invoke", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
ig.Emit(OpCodes.Call, cm);
ig.Emit(OpCodes.Stloc_2);
//若out参数数量>0 循环处理返回的对象列表中的值给out参数地址
if (outstart < PTS.Length)
{
for (int i = 1; i < PTS.Length - outstart + 1; i++)
{
//将参数加载到堆栈
ig.Emit(OpCodes.Ldarg, outstart + i);
//加载返回值
ig.Emit(OpCodes.Ldloc_2);
//将返回值的索引加载到堆栈
ig.Emit(OpCodes.Ldc_I4, i);
//将索引楚的数据地址加载到堆栈
ig.Emit(OpCodes.Ldelem_Ref);
//转换类型为字符串
ig.Emit(OpCodes.Castclass, typeof(string));
//将转换过的字符串地址放入参数位置
ig.Emit(OpCodes.Stind_Ref);
}
}
ig.Emit(OpCodes.Ldloc_2);
//加载返回值索引0
ig.Emit(OpCodes.Ldc_I4_0);
//引用返回值索引0处的数据
ig.Emit(OpCodes.Ldelem_Ref);
//转换为字符串
ig.Emit(OpCodes.Castclass, typeof(string));
//将字符串加载到局部变量0
ig.Emit(OpCodes.Stloc_0);
//将变量0入栈
ig.Emit(OpCodes.Ldloc_0);
//返回
ig.Emit(OpCodes.Ret);
Type O = T.CreateType();
ConstructorInfo ci = O.GetConstructor(Type.EmptyTypes);
object s = ci.Invoke(new object[] { });
PropertyInfo piurl = O.GetProperty("Url");
piurl.SetValue(s, url, null);
MethodInfo mi = O.GetMethod(commandname);
object rtobj = mi.Invoke(s, args);
rt = rtobj.ToString();
s = null;
return rt;
}
动态生成webservice的soap调用的方案可以参考一下,这里可以做一个判断比如通过文件是否存在来判断dll是否生成,然后用反射调用,没有生成用这个生成以后调用AB.Save方法可以保存到本地using (var fs = File.Open("a.exe", FileMode.Open))
{
fs.Position = 12345;
fs.WriteByte(0x88);
}
改很简单,值一块钱。
知道改哪里,值一万块。