使用反射可以解决你的问题:
a) 使用反射枚举您感兴趣的类中的所有公共方法,例如:
var methods = typeof(SomeClass).GetMethods(BindingFlags.Instance | BindingFlags.Public);
b) 使用此列表将您的服务的源代码生成为字符串
StringBuilder source = new StringBuilder();
source.AppendLine("using System;");
source.AppendLine("using System.ServiceModel;");
source.AppendLine("[ServiceContract]");
source.AppendLine("public class DynamicService {");
// Here for each MethodInfo from list generate a method source like
foreach (var method in methods)
{
if (method.ReturnType == typeof(void))
continue;
string parameters = string.Join(", ", method.GetParameters().Select(pi => string.Format("{0} {1}", pi.ParameterType.Name, pi.Name)));
string arguments = string.Join(", ", method.GetParameters().Select(pi => pi.Name));
source.AppendFormat("[OperationContract]");
source.AppendFormat("public {0} {1}({2})", method.ReturnType.Name, method.Name, parameters);
source.AppendFormat("{{ return ConsoleApplication.Helpers.{0}({1}); }}", method.Name, arguments);
}
source.AppendLine("}");
注意:您需要在这里进行一些过滤,例如过滤掉ToString 等。作为示例,我绕过了所有 void 方法。
c) 使用CSharpCodeProvider编译服务源:
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters param = new CompilerParameters();
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.ReferencedAssemblies.Add("System.Runtime.Serialization.dll");
param.ReferencedAssemblies.Add("System.ServiceModel.dll");
param.ReferencedAssemblies.Add("System.dll");
param.ReferencedAssemblies.Add("ConsoleApplication.exe");
CompilerResults result = codeProvider.CompileAssemblyFromSource(param, source.ToString());
注意:在这里您可以添加对包含您的帮助类的程序集的引用,在我的示例中为ConsoleApplication.exe。
d) 将您的动态服务用作普通服务。例如,您可以自行托管它:
if (!result.Errors.HasErrors)
{
Type type = result.CompiledAssembly.GetType("DynamicService");
var instance = Activator.CreateInstance(type);
Uri baseAddress = new Uri("http://localhost:80/hello");
using (ServiceHost host = new ServiceHost(type, baseAddress))
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
}
e) 然后你就有了:
f) 如果您想在 IIS 中托管此服务,则必须提供您自己的自定义 ServiceHostFactory