使用具有IQueryable <dynamictype>返回类型的CIL MethodBuilder创建动态方法

时间:2017-03-08 07:47:13

标签: c# wcf-data-services cil

我已经为SOAP和REST编写了动态Web服务。现在需要创建OData Web服务,该服务具有根据WCF数据服务规范返回IQueryable接口的操作。 我正在创建一个基于IL Emit语句的动态方法。但是我无法将返回类型分配给IQueryable的MethodBuilder。

具体来说,我无法使用MethodBuilder.SetReturnType方法设置返回参数,因为返回类型IQueryable是在运行时生成的。

    public class MainClass
    {       

    public static void Main()
            {
                AssemblyBuilder serviceAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyDynamicAsm"), AssemblyBuilderAccess.RunAndSave);
                ModuleBuilder serviceModule = serviceAsmBuilder.DefineDynamicModule("MyDynamicAsm", "MyDynamicAsm.dll");
                TypeBuilder serviceTypeBuilder = serviceModule.DefineType("MyDynamicType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass,
                    typeof(DataService<WebServerResult>) );

                //This is the problem, as I do not have this class at compile
               //time. I get this class at run time                
                Type returnType = typeof(IQueryable<WebServerResult>);
                MethodBuilder MethodBldr = serviceTypeBuilder.DefineMethod("OperationName", MethodAttributes.Public, returnType, Type.EmptyTypes);
                ILGenerator methodGenerator = MethodBldr.GetILGenerator();
                methodGenerator.Emit(OpCodes.Ret);
            }
        }
        //This is just for reference. This code does not exist at design time
        [DataContract]
        public class WebServerResult
        {
            [DataMember]
            public List<Variable> Variables { get; set; }
            public IQueryable<Variable> ODataResultList
            {
                get { return Variables.AsQueryable<Variable>(); }
            }
        }

        [DataServiceKey("VariableName")]
        [DataContract(Namespace = "")]
        public class Variable
        {
            [DataMember]
            public string VariableName { get; set; }
            [DataMember]
            public string VariableValue { get; set; }
            [DataMember]
            public string VariableType { get; set; }
        }

有人能为我提供IL发射代码中方法生成的蓝图吗?

1 个答案:

答案 0 :(得分:2)

要创建包含在运行时之前未知的类型参数的泛型类型,您必须使用Type.MakeGenericType方法。您的代码可能如下所示:

//get the dynamic type from somewhere
Type unknownType = ...;

//get open generic base type
Type openGeneric = typeof(IQueryable<>);

//create closed generic type with the unknown type as generic type parameter
Type closedGeneric = openGeneric.MakeGenericType(unknownType);

//use the closed type for whatever you want
Type returnType = closedGeneric;