Причина, по которой MethodBuilder.DefineParameter не может установить имя параметра? - PullRequest
3 голосов
/ 02 февраля 2010

Я создаю интерфейс на основе существующего интерфейса для проблем WCF, но у меня "DefineParameter" не задает имена параметров (параметры метода созданного типа не имеют имени).
Можете ли вы увидеть причинупочему?

    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 iService.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;
    }

1 Ответ

11 голосов
/ 02 февраля 2010

Я понял, поэтому сообщу.
Ответ в том, как я использовал функцию DefineParameter.
Функция GetParameters возвращает информацию о параметрах предоставленного метода.
Но функция DefineParameter устанавливает информацию о параметрах для всех параметров (включая возвращаемый параметр), поэтому позиции меняются: при использовании DefineParameter позиция 0 ссылается на возвращаемый параметр, а параметры вызова начинаются с позиции 1.

См. Исправление:

method.DefineParameter(param.Position+1, ParameterAttributes.None, param.Name);

STFM (см. Руководство по fu ....):

MethodBuilder.DefineParameter Method @ MSDN

Приветствия:)

...