I'm creating an interface based on an existing interface for WCF concerns, but I have the "DefineParameter" not setting the parameter names (method parameters of the created type have no name).
Can you see a reason why? public static Type MakeWcfInterface(Type iService)
{
AssemblyName assemblyName = new AssemblyName(String.Format("{0}_DynamicWcf", iService.FullName));
String moduleName = String.Format("{0}.dll", assemblyName.Name);
String ns = iService.Namespace;
if (!String.IsNullOrEmpty(ns)) ns += ".";
// Create assembly
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
// Create module
var module = assembly.DefineDynamicModule(moduleName, false);
// Create asynchronous interface type
TypeBuilder iWcfService = module.DefineType(
String.Format("{0}DynamicWcf", iService.FullName),
TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract
);
// Set ServiceContract attributes
iWcfService.SetCustomAttribute(ReflectionEmitHelper.BuildAttribute<ServiceContractAttribute>(null,
new Dictionary<string, object>() {
{ "Name", iService.Name },
}));
iWcfService.SetCustomAttribute(ReflectionEmitHelper.BuildAttribute<ServiceBehaviorAttribute>(null,
new Dictionary<string, object>() {
{ "InstanceContextMode" , InstanceContextMode.Single }
})
);
foreach (var method in iServic开发者_StackOverflow社区e.GetMethods())
{
BuildWcfMethod(iWcfService, method);
}
return iWcfService.CreateType();
}
private static MethodBuilder BuildWcfMethod(TypeBuilder target, MethodInfo template)
{
// Define method
var method = target.DefineMethod(
template.Name,
MethodAttributes.Abstract | MethodAttributes.Virtual
| MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.VtableLayoutMask | MethodAttributes.HideBySig,
CallingConventions.Standard,
template.ReturnType,
template.GetParameters().Select(p => p.ParameterType).ToArray()
);
// Define parameters
foreach (ParameterInfo param in template.GetParameters())
{
method.DefineParameter(param.Position, ParameterAttributes.None, param.Name);
}
// Set OperationContract attribute
method.SetCustomAttribute(ReflectionEmitHelper.BuildAttribute<OperationContractAttribute>(null, null));
return method;
}
I got it, so I let you know.
The answer is in the way I used the DefineParameter function.
The GetParameters function returns info about the parameters of a provided method.
But the DefineParameter function set parameter info for all parameters (including return parameter), so postions shift : using DefineParameter, position 0 references the return parameter, and call parameters begin at postion 1.
See the fix :
method.DefineParameter(param.Position+1, ParameterAttributes.None, param.Name);
STFM (see the fu.... manual) :
MethodBuilder.DefineParameter Method @ MSDN
Cheers :)
精彩评论