Create a lambda expression with a new anonymous type at runtime

anonymous-types c# entity-framework expression-trees reflection

Question

I want to call a method that anticipates the following parameter:

Expression<Func<sometype, 'a>> expr

I must create this argument at runtime since I won't know the anonymous type's appearance beforehand; it may include any number of fields:

x => new { a=x.a, b=x.b, c=x.c, etc... }

The problem is: How can I build this lambda expression at runtime from that? I can produce a type at runtime that has the same'signature' (Is that the right term for this?) as the desired anonymous type. Particularly Expression The fact that I must supply a constructorInfo to New that I must get from an existing type (which may be an anonymous type, but which I cannot create at runtime) annoys me. Or is there a method for doing that?).

Update (some context as requested in the comments)

The technique I want to use is:

DependentNavigationPropertyConfiguration.HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression)

I want to accomplish this in order to automatically add the key of that base class in the foreign key of a navigation property to an entity that derives from a certain base class. I only know the type TKey at runtime since an object may have many key fields of any type.

2
5
5/30/2013 2:48:54 PM

Accepted Answer

Use a different technique:

public static void Main()
{
    var myExpression = Express(str => new { 
        String = str, 
        Length = str.Length 
    });

    // We can compile/use it as well...
    var compiledExpression = myExpression.Compile();
    var anonymousOutput = compiledExpression("Input String");

    Console.WriteLine(anonymousOutput.String); // Output: Input String
    Console.WriteLine(anonymousOutput.Length); // Output: 12

    Debug.WriteLine(myExpression); // Output: "str => new <>f__AnonymousType0`2(String = str, Length = str.Length)"
    Console.ReadLine();
}


static Expression<Func<String, T>> Express<T>(Expression<Func<String, T>> expression)
{
    return expression;
}

However, take note that in my case, the initial typeString () must be made clear up front.

Update:

I'll give you a straightforward example of how to dynamically build a type because that's what it seems like you're attempting to accomplish.

public static void Main()
{
        // Create an anonymous type with two fields
    Type myAnonymousType = CreateNewType<String, Int32>();
    dynamic myAnon = Activator.CreateInstance(myAnonymousType);

    myAnon.FieldA = "A String";
    myAnon.FieldB = 1234;


    Console.WriteLine(myAnon.FieldA); // Output : "AString"
    Console.WriteLine(myAnon.FieldB); // Output : 1234
    Console.ReadLine();
}

public static Type CreateNewType<TFieldTypeA, TFieldTypeB>()
{
    // Let's start by creating a new assembly
    AssemblyName dynamicAssemblyName = new AssemblyName("MyAsm");
    AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
    ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAsm");

    // Now let's build a new type
    TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("MyAnon", TypeAttributes.Public);

    // Let's add some fields to the type.
    FieldInfo dynamicFieldA = dynamicAnonymousType.DefineField("FieldA", typeof(TFieldTypeA), FieldAttributes.Public);
    FieldInfo dynamicFieldB = dynamicAnonymousType.DefineField("FieldB", typeof(TFieldTypeB), FieldAttributes.Public);

    // Return the type to the caller
    return dynamicAnonymousType.CreateType();
}

This is a bit more difficult, as you can see. However, if you like to learn more about the subject, you should absolutely consultReflectoin.Emit .

10
5/30/2013 2:32:07 PM

Expert Answer

An attribute of compilers are anonymous types. You will need to utilize meta-programming if you can't get the compiler to build them at compile time.TypeBuilder maybe perhapsCSharpCodeProvider You may find that utilizing tuples is preferable since they are at least simple to build (you may useTuple.Create very simply).

Regarding the phrase, I advise writing it asExpression<Func<sometype, object>> – which is applicable to any composition. The symbol is inspecting.Expression can naturally see what kind it is.

3
5/30/2013 2:00:59 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow