C# LINQ表达式投影到匿名类型
我创建了一个LINQ表达式,它将一个序列投影到新的匿名类型序列中,正如我在这里发现的那样 下面是我想要执行的表达式:C# LINQ表达式投影到匿名类型,c#,linq,expression,C#,Linq,Expression,我创建了一个LINQ表达式,它将一个序列投影到新的匿名类型序列中,正如我在这里发现的那样 下面是我想要执行的表达式: Document doc = ....; doc.AllStatements.Select(s => new { field = s.Amount }); 这是括号内选择器的运行时表示形式: {t => new field;Decimal;() {field = t.Amount}} 这是整个表达式的运行时表示 {System.Linq.Enumerable+&l
Document doc = ....;
doc.AllStatements.Select(s => new { field = s.Amount });
这是括号内选择器的运行时表示形式:
{t => new field;Decimal;() {field = t.Amount}}
这是整个表达式的运行时表示
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;() {field = t.Amount})}
如果我尝试使用以下多字段匿名类型:
doc.AllStatements.Select(s => new { field = s.Amount, field2 = s.Account });
我明白了:
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;field1;Nullable`1;() {field = t.Amount, field1 = t.Account})}
有人能帮我破译这个吗
更新:
这是我真正的电话:
var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new field=Amount, field1=Account)");
但是,DoExpressions函数背后有很多解析和LINQ表达式,大约500行代码
更新2:
首先,这里是一段代码:
Dokument doc = db.Dokumenti.First(); // Proper document, entity object;
var res = Expressions.DoExpression(
typeof(Dokument),
doc,
"SviFinStavovi.Select(new id=Iznos, dsc=Opis)"
);
SviFinStavovi是Dokument的导航属性,Iznos和Opi是SviFinStavovi基础类型的属性
不过,这两行代码不会引发异常。只有当我尝试枚举res时才会抛出异常。您有上面提到的那个些
如果我把SviFinStavovi.SelectIznos放进去,那就行了
这是DoExpression:
public static object DoExpression(Type t, object obj, string expression){
ParameterExpression pe = Expression.Parameter(obj.GetType(), "objekat");
Expression SelectExpr = Expressions.ResolveCompleteExpression(pe, expression.Prepare());
return Expression.Lambda(SelectExpr, pe).Compile().DynamicInvoke(obj);}
ResolveCompleteExpression解析整个过程
现在,这是我从这个网站上获得的功能,上面的链接,我添加了它,它会带来麻烦:
public static Expression SelectDynamic(Expression expr, IEnumerable<string> fieldNames)
{
Type source = expr.Type.GetGenericArguments()[0];
Dictionary<string, PropertyInfo> sourceProperties = new Dictionary<string, PropertyInfo>();
foreach (string arg in fieldNames) sourceProperties.Add(arg.Split('=')[0].Trim(), source.GetProperty(arg.Split('=')[1].Trim()));
Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicTypeWrapper(sourceProperties);
ParameterExpression sourceItem = Expression.Parameter(source, "t");
IEnumerable<MemberBinding> bindings = dynamicType.GetFields().Select(p => Expression.Bind(p, Expression.Property(sourceItem, sourceProperties[p.Name]))).OfType<MemberBinding>();
Expression selector = Expression.Lambda(Expression.MemberInit(
Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)), bindings), sourceItem);
return Expression.Call(typeof(Queryable), "Select", new Type[] { source, dynamicType }, expr, selector);
}
此时expr将正确表示doc.SviFinStavovi,字段名为[id=Iznos][dsc=Opis]
现在,这不是我的代码,我只是稍微调整了一下以适合我。这实际上是上面代码段的最后一行代码。仅用于展开堆栈并进行编译
对不起,如果这可能没有任何意义。如果您需要任何澄清,请询问 我认为select需要在new之后的字段周围加上括号
Select("new(<property1>,<property2>,...)");
var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new (field=Amount, field1=Account))");
我不能做匿名投影,但我用板条箱装了一个小班,然后投影到其中:
public class LookupModel
{
public LookupModel(int id, string dsc)
{
ID = id;
DSC = dsc;
}
public int ID { get; set; }
public string DSC { get; set; }
}
所以用这个:
function LINQSelectNew(Expression expr, string[] args)
{
Type type = expr.Type.GetGenericArguments()[0];
ParameterExpression parameter = Expression.Parameter(type, type.Name);
List<Expression> lista = new List<Expression>();
foreach (string s in args) lista.Add(Expressions.ResolveCompleteExpression(parameter, s.Prepare()));
Expression New = Expression.New(typeof(LookupModel).GetConstructor(lista.Select(e => e.Type).ToArray()), lista.ToArray());
return Expression.Call(
typeof(Queryable),
"Select",
new Type[] { type, New.Type },
expr,
Expression.Lambda(New, new ParameterExpression[] { parameter }));
}
希望这对某人有所帮助…您从哪里得到这些错误?在VS的监视窗口中?是的,我的结果是var类型的。然后我在后面放了一个断点,然后检查它,并说“扩展结果视图将枚举IEnumerable”。然后我得到了那个些错误手表里面的字符串不是C代码,所以你们不能用这种方式执行它。我可能并没有全部说出来。这是我的电话:var res=Expressions.DoExpressiontypeofDocument,doc,AllStatements;但是,在解析和创建LINQ表达式的背后大约有500行代码。Res是所有操作的最终结果,我得到了上面提到的错误,请尝试在所有异常上设置break。不幸的是,我怀疑你的错误在那500行中的某个地方。
public class LookupModel
{
public LookupModel(int id, string dsc)
{
ID = id;
DSC = dsc;
}
public int ID { get; set; }
public string DSC { get; set; }
}
function LINQSelectNew(Expression expr, string[] args)
{
Type type = expr.Type.GetGenericArguments()[0];
ParameterExpression parameter = Expression.Parameter(type, type.Name);
List<Expression> lista = new List<Expression>();
foreach (string s in args) lista.Add(Expressions.ResolveCompleteExpression(parameter, s.Prepare()));
Expression New = Expression.New(typeof(LookupModel).GetConstructor(lista.Select(e => e.Type).ToArray()), lista.ToArray());
return Expression.Call(
typeof(Queryable),
"Select",
new Type[] { type, New.Type },
expr,
Expression.Lambda(New, new ParameterExpression[] { parameter }));
}
var res = Expressions.DoExpression(
typeof(Dokument),
doc,
"SviFinStavovi.Select(new LookupModel(amount, amount.ToString()))"
);