-1

I have written the dynamic web services for SOAP and REST. Now need to create OData web services that has operations that return IQueryable Interface as per WCF data service specification. I am creating a dynamic method based on IL Emit statements. But am not able to assign the return type to the MethodBuilder which is IQueryable.

To be specific, I am not able to set the return parameter using MethodBuilder.SetReturnType Method as the return type IQueryable is generated at run time.

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

Can someone provide me the blue print of the method generation in IL emit code?

badari
  • 91
  • 1
  • 8
  • Possible duplicate of [Dynamic method using MethodBuilder with IQueryable return type](http://stackoverflow.com/questions/42654679/dynamic-method-using-methodbuilder-with-iqueryabledynamictype-return-type) – thehennyy Mar 08 '17 at 08:00
  • Please undo the downvote.. i cannot ask new questions.. I have deleted my original post – badari Mar 08 '17 at 08:14
  • I did not vote. Anyway ill ask the same question here again. What is still unclear? You just have to pass your type object as the only parameter to the SetReturnType method. – thehennyy Mar 08 '17 at 08:30
  • I am not able to set the return type. I have to set the return type at compile time.. but the IQueryable<> does not take run time references. I create run time data contract for each of the operations that i assign it to IQueryable. Like this IQueryable. Hope this is clear. – badari Mar 08 '17 at 08:36
  • So your real problem is that you are unable to construct a generic type object where the type parameter is set at runtime? Then you should use the Type.MakeGenericType method. – thehennyy Mar 08 '17 at 09:41
  • I will try this. Thanks. – badari Mar 08 '17 at 09:52
  • Looks like it does not work.. IQueryable does not except generic types at least in case of WCF OData service.. Do you have any inputs on this? – badari Mar 08 '17 at 11:21
  • It is still very unclear what you are doing. Can you please provide all the code you are using, aswell as the error/exception you are getting and what you are expecting instead. A [mcve](http://stackoverflow.com/help/mcve) would be good. – thehennyy Mar 08 '17 at 12:43
  • Added the code.. and look at the commented line of code. I am not able to set the return type as I dont have it at design time – badari Mar 08 '17 at 13:48

1 Answers1

2

To create a generic type that contains type parameters that are unknown until runtime you have to use the Type.MakeGenericType method. Your code could look like this:

//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;
thehennyy
  • 4,020
  • 1
  • 22
  • 31