最近我需要做一些类似的事情(中继方法调用)。最终我生成了一个类型,在运行时动态转发方法调用。
对于您的用例,实现将类似于此。首先创建一个描述您的服务的接口。您将在代码中任何想要调用服务的地方使用此接口。
public interface IMyService
{
[ServiceImport("service_name")]
string ServiceName(int arg1, string arg2);
}
然后运行代码以动态生成实现此接口的类。
MethodInfo executeMethod = typeof(Services).GetMethod("Execute");
AssemblyName assemblyName = new AssemblyName("MyAssembly");
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run, (IEnumerable<CustomAttributeBuilder>)null);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType("MyClass", TypeAttributes.Class | TypeAttributes.Public, typeof(object), new Type[] { typeof(IMyService) });
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
foreach (MethodInfo method in typeof(IMyService).GetMethods())
{
ServiceImportAttribute attr = method
.GetCustomAttributes(typeof(ServiceImportAttribute), false)
.Cast<ServiceImportAttribute>()
.SingleOrDefault();
var parameters = method.GetParameters();
if (attr == null)
{
throw new ArgumentException(string.Format("Method {0} on interface IMyService does not define ServiceImport attribute."));
}
else
{
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
method.Name,
MethodAttributes.Public | MethodAttributes.Virtual,
CallingConventions.HasThis,
method.ReturnType,
parameters.Select(p => p.ParameterType).ToArray());
ILGenerator methodGenerator = methodBuilder.GetILGenerator();
LocalBuilder paramsLocal = methodGenerator.DeclareLocal(typeof(object[]));
methodGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
methodGenerator.Emit(OpCodes.Newarr, typeof(object));
methodGenerator.Emit(OpCodes.Stloc, paramsLocal);
for (int i = 0; i < parameters.Length; i++)
{
methodGenerator.Emit(OpCodes.Ldloc, paramsLocal);
methodGenerator.Emit(OpCodes.Ldc_I4, i);
methodGenerator.Emit(OpCodes.Ldarg, (short)(i + 1));
if (parameters[i].ParameterType.IsValueType)
{
methodGenerator.Emit(OpCodes.Box, parameters[i].ParameterType);
}
methodGenerator.Emit(OpCodes.Stelem, typeof(object));
}
methodGenerator.Emit(OpCodes.Ldstr, attr.Name);
methodGenerator.Emit(OpCodes.Ldloc, paramsLocal);
methodGenerator.Emit(OpCodes.Call, executeMethod);
methodGenerator.Emit(OpCodes.Ret);
}
}
Type generatedType = typeBuilder.CreateType();
IMyService service = (IMyService)generatedType.GetConstructor(new Type[] { }).Invoke(new object[] { });
service.ServiceName(1, "aaa");
这个解决方案可能有点凌乱,但如果您想节省创建代码的时间,它还是可以很好地工作的。
请注意,创建动态类型会影响性能。但通常在初始化期间完成,不应对运行时产生太大影响。
或者,我建议您看看PostSharp,它允许您在编译时生成代码。但这是一个付费商业解决方案。