在运行时新的匿名类型创建一个lambda表达式 [英] Create a lambda expression with a new anonymous type at runtime

查看:305
本文介绍了在运行时新的匿名类型创建一个lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要调用一个期望的方法像这样的参数:

I want to invoke a method that expects a parameter like this:

Expression<Func<sometype, 'a>> expr



我需要构建在运行时此参数,因为我不知道什么匿名类型将看起来像以前一样;它可能有场任意数量的:

I need to construct this parameter at runtime, because I won't know what the anonymous type will look like before; it could have any amount of fields:

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



我可以在运行时创建一个类型,具有相同的签名(那是正确的词来形容?)作为期望的匿名类型,但问题是:我如何在从运行构建这个lambda表达式?尤其是Expression.New是缠着我,因为我需要一个constructorInfo传递给它,我有从现有的类型(这的确可以是一个匿名类型来获得,但我不能在运行时创建一个匿名类型。或者是有一种方式来做到这一点?)。

I can create a type at runtime that has the same 'signature' (Is that the correct word for this?) as the desired anonymous type, but the question is: How do I construct this lambda expression at runtime from that? Especially Expression.New is bugging me, because I need to pass a constructorInfo to it that I have to get from an existing type (which can indeed be an anonymous type, but I can't create an anonymous type at runtime. Or is there a way to do that?).

更新(有的在评论请求的上下文)

Update (some context as requested in the comments)

我要调用的方法是:

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

我想这样做是自动进行导航属性的原因从某个基类继承的实体包括基类的外键的键。因为一个实体可以是任意类型,类型TKEY的在运行时只知道我的多个重点领域。

The reason I want to do this is to automatically make a navigation property to an entity that inherits from a certain base class include the key of that base class in the foreign key. Because an entity can have multiple key fields of any type, the type TKey is only known to me at runtime.

推荐答案

使用一个单独的方法:

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

不过

请注意,该起点类型(在我的例子字符串)必须知道前面

更新

由于这听起来像你正在试图做的是动态创建一个类型,我给你如何做一个简单的例子。

Since what it sounds like you're trying to do is dynamically create a type, I'll give you a simple example of how to do that.

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



正如你所看到的,这是一个比较复杂的。如果你想进一步研究的话题,虽然,绝对引用 Reflectoin.Emit

这篇关于在运行时新的匿名类型创建一个lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆