- 每次调用都会通过WebClient请求以下WebSerivce的wsdl描述文件(没有必要)
- 每次调用动态生成dll,如果请求数量比较大时,会造成CPU很高
- 每次都会加载新生成dll(程序集),然后反射.
private static object CallWebService(string url, string methodname, object[] args)
{
string nameSpace = "qiufeng.webservice";
try
{
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
string classname = sd.Services[0].Name;
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
sdi.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
CodeNamespace cn = new CodeNamespace(nameSpace);
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
CompilerParameters cplist = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
OutputAssembly = string.Format("{0}/{1}.dll", Directory.GetCurrentDirectory(), "WebService1")
};
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults cr = csc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}
Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(nameSpace + "." + classname, true, true);
object obj = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(methodname);
object objs = mi.Invoke(obj, args);
return objs;
}
catch (Exception ex)
{
return ex;
}
}
string url = "http://localhost:50309/WebService1.asmx";
object o1 = CallWebService(url, "GetName", new object[] { "Hello" });
Console.WriteLine(o1);
优化第一版
private static object CallWebService_Optimize2(string url, string methodname, object[] args)
{
const string nameSpace = "qiufeng.webservice";
object objs = null;
try
{
if (serviceAssm == null)
{
string filePath = string.Format("{0}/{1}.dll", Directory.GetCurrentDirectory(), nameSpace);
if (File.Exists(filePath))
{
serviceAssm = Assembly.LoadFrom(filePath);
fullName = ConfigurationManager.AppSettings[nameSpace];
}
else
{
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
string classname = sd.Services[0].Name;
string classFullName = $"{nameSpace}.{classname}";
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
sdi.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
CodeNamespace cn = new CodeNamespace(nameSpace);
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
CompilerParameters cplist = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
OutputAssembly = filePath
};
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");
CompilerResults cr = csc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(Environment.NewLine);
}
throw new Exception(sb.ToString());
}
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings[nameSpace].Value = classFullName;
config.AppSettings.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
fullName = classFullName;
serviceAssm1 = Assembly.LoadFrom(filePath);
}
}
Type t = serviceAssm.GetType(fullName, true, true);
object obj = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(methodname);
objs = mi.Invoke(obj, args);
return objs;
}
catch (Exception ex)
{
return ex;
}
}
发现调整后,性能还是很明显的.调整前在BenchmarkDotNet.没有显示时间.
其他的优化思路
每次调用调用WebSerivce的时候都会对生成的请求代理类,进行反射创建.可以改为委托创建,并缓存委托.