在运行时在c#中获取列表的项目类型 [英] Getting type of items of a List at run-time in c#

查看:238
本文介绍了在运行时在c#中获取列表的项目类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个这样的集合:

  var collection = new List< object> {1,2.2,string,'c'}; 

可以获取每个收藏品的类型:

  var myVariable = collection.Select(item => item.GetType())

但是我需要在运行时创建这个表达式。
我必须动态地创建一个类似于 myVariable 的东西,但是如何?!



调试器显示我的价值 myVariable 的内部表达式如下:

  {System.Linq.Enumerable + WhereSelectListIterator`2 [System.Object,System.Type]} 

EDIT1



问题的解释:
假设我需要选择对象的一个​​属性。我这样写这个查询:

  var lst = new List< MyClass> 
{
new MyClass {Name =myName1,Value = 1},
new MyClass {Name =myName2,Value = 2}
};
var oneProperty = lst.Select(item => new {SelectedProp = item.Name});

结果是匿名类型的列表包含2个项目:myName1&myName2。
现在我要添加另一个属性到结果列表,显示所选属性的类型。以下代码让我这样列出:

  var oneProperty = lst.Select(item => new {SelectedProp = item.Name ,TypeOfProp = item.GetType()}); 

问题是在运行时创建这样的表达式,以将表达式赋予实体框架,并执行表达方式。问题是否清除?

解决方案

鉴于您最近的编辑,以下是运行时编译一个表达式如下:

  item => new AnonymousType(){SelectProp = item.name,TypeOfProp = item.GetType()} 






我已经添加了评论来显示表达式的构造方式。您可以根据自己的需要进行调整。

  [事实] 
public void CreateExpression()
{
键入argType = typeof(MyClass);
string propertyName =Name;

ParameterExpression paramExpression = Expression.Parameter(argType,item);

//创建item.Name和item.GetType()表达式
var propertyAccessExpression = Expression.Property(paramExpression,propertyName);
var getTypeExpression = Expression.Call(paramExpression,GetType,Type.EmptyTypes);

键入anonType = CreateAnonymousType< String,Type>(SelectedProp,TypeOfProp);

//SelectProp = item.name
MemberBinding assignment1 = Expression.Bind(anonType.GetField(SelectedProp),propertyAccessExpression);
//TypeOfProp = item.GetType()
MemberBinding assignment2 = Expression.Bind(anonType.GetField(TypeOfProp),getTypeExpression);

//new AnonymousType()
var creationExpression = Expression.New(anonType.GetConstructor(Type.EmptyTypes));

//new AnonymousType(){SelectProp = item.name,TypeOfProp = item.GetType()}
var initialization = Expression.MemberInit(creationExpression,assignment1,assignment2);

//item => new AnonymousType(){SelectProp = item.name,TypeOfProp = item.GetType()}
表达式expression = Expression.Lambda(初始化,paramExpression) ;
}

您需要这种方法才能创建一个新的匿名类型:

  public static Type CreateAnonymousType< TFieldA,TFieldB>(string fieldNameA,string fieldNameB)
{
AssemblyName dynamicAssemblyName = new的AssemblyName( TempAssembly);
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName,AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule(TempAssembly);

TypeBuilder dynamicAnonymousType = dynamicModule.DefineType(AnonymousType,TypeAttributes.Public);

dynamicAnonymousType.DefineField(fieldNameA,typeof(TFieldA),FieldAttributes.Public);
dynamicAnonymousType.DefineField(fieldNameB,typeof(TFieldB),FieldAttributes.Public);

return dynamicAnonymousType.CreateType();
}


I need an expression that gets type of every item of a collection.

I have a collection like this:

var collection = new List<object>{1,2.2,"string",'c'};

It's possible to get type of every item of collection like this:

var myVariable= collection.Select(item => item.GetType())

But I need creation of this expression at run-time. I have to create something like myVariable dynamically, but how?!

Debugger shows me value of internal expression of myVariable like this:

{System.Linq.Enumerable+WhereSelectListIterator`2[System.Object,System.Type]}

EDIT1

Explanation of problem: Assume that I need to select one property of an object. I cat write this query like this:

var lst = new List<MyClass>
        {
            new MyClass {Name = "myName1", Value = 1},
            new MyClass {Name = "myName2", Value = 2}
        };
        var oneProperty = lst.Select(item => new {SelectedProp=item.Name});

result is a list of type anonymous contains 2 items: "myName1"&"myName2". Now I want to add another property to resulted list that shows the type of selected property. The following code gets me thus list:

            var oneProperty = lst.Select(item => new {SelectedProp=item.Name,TypeOfProp=item.GetType() });

The problem is to create such expression at run-time to give the expression to entity framework and it executes the expression. Is the problem cleared?

解决方案

Given your recent edit, here's how to compile an expression such as the following at run-time:

item => new AnonymousType() { SelectProp = item.name, TypeOfProp = item.GetType() }


I've added comments to show how the expression is being constructed. You can adapt this to your needs.

[Fact]
public void CreateExpression()
{
    Type argType = typeof (MyClass);
    string propertyName = "Name";

    ParameterExpression paramExpression = Expression.Parameter(argType, "item");

    //Create "item.Name" and "item.GetType()" expressions
    var propertyAccessExpression = Expression.Property(paramExpression, propertyName); 
    var getTypeExpression = Expression.Call(paramExpression, "GetType", Type.EmptyTypes);

    Type anonType = CreateAnonymousType<String, Type>("SelectedProp", "TypeOfProp");

    //"SelectProp = item.name"
    MemberBinding assignment1 = Expression.Bind(anonType.GetField("SelectedProp"), propertyAccessExpression);
    //"TypeOfProp = item.GetType()"
    MemberBinding assignment2 = Expression.Bind(anonType.GetField("TypeOfProp"), getTypeExpression);

    //"new AnonymousType()"
    var creationExpression = Expression.New(anonType.GetConstructor(Type.EmptyTypes));

    //"new AnonymousType() { SelectProp = item.name, TypeOfProp = item.GetType() }"
    var initialization = Expression.MemberInit(creationExpression, assignment1, assignment2);

    //"item => new AnonymousType() { SelectProp = item.name, TypeOfProp = item.GetType() }"
    Expression expression = Expression.Lambda(initialization, paramExpression);
}

You'll need this method to create a new anonymous type:

public static Type CreateAnonymousType<TFieldA, TFieldB>(string fieldNameA, string fieldNameB)
{
    AssemblyName dynamicAssemblyName = new AssemblyName("TempAssembly");
    AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
    ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("TempAssembly");

    TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("AnonymousType", TypeAttributes.Public);

    dynamicAnonymousType.DefineField(fieldNameA, typeof(TFieldA), FieldAttributes.Public);
    dynamicAnonymousType.DefineField(fieldNameB, typeof(TFieldB), FieldAttributes.Public);

    return dynamicAnonymousType.CreateType();
}

这篇关于在运行时在c#中获取列表的项目类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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