C# LINQ - 根据运行时定义的属性选择动态对象

我一直在尝试创建一个表达式,它可以将强类型的 EF Core 实体投影到一个动态对象中,该对象包含一个在运行时使用 REST API 调用定义的列表。


这是我到目前为止所拥有的:


Expression<Func<Message, dynamic>> DynamicFields(IEnumerable<string> fields)

{

    var xParameter = Expression.Parameter(typeof(Message), "o");

    var xNew = Expression.New(typeof(ExpandoObject));


    var bindings = fields.Select(o => {

        var mi = typeof(Message).GetProperty(o);

        var xOriginal = Expression.Property(xParameter, mi);

        return Expression.Bind(mi, xOriginal);

    });


    var xInit = Expression.MemberInit((dynamic)xNew, bindings);


    return Expression.Lambda<Func<Message, dynamic>>(xInit, xParameter);

}

感觉就像我非常接近,但这在运行时会爆炸,说明 X 属性不是 ExpandoObject 的成员。我尝试改变动态和 ExpandoObject 的使用,但似乎没有任何效果 - 这甚至可能吗?


如果我为 Message 切换出 dyanmic / ExpandoObject,它工作得很好,但会返回 Message 类的一个实例,其所有属性都为默认值。


以前有人做过吗?


波斯汪
浏览 232回答 2
2回答

www说

不能直接投影到ExpandoObject/ dynamic。但是您可以在运行时投影到动态创建的类型。参见例如Microsoft.EntityFrameworkCore.DynamicLinq包 - 动态数据类。如果您以 nuget 的形式安装该软件包(您可以自己开发类似的功能,但您应该基本上实现该软件包的所有功能),则可以按如下方式实现该方法:using System.Linq.Dynamic.Core;static Expression<Func<TSource, dynamic>> DynamicFields<TSource>(IEnumerable<string> fields){&nbsp; &nbsp; var source = Expression.Parameter(typeof(TSource), "o");&nbsp; &nbsp; var properties = fields&nbsp; &nbsp; &nbsp; &nbsp; .Select(f => typeof(TSource).GetProperty(f))&nbsp; &nbsp; &nbsp; &nbsp; .Select(p => new DynamicProperty(p.Name, p.PropertyType))&nbsp; &nbsp; &nbsp; &nbsp; .ToList();&nbsp; &nbsp; var resultType = DynamicClassFactory.CreateType(properties, false);&nbsp; &nbsp; var bindings = properties.Select(p => Expression.Bind(resultType.GetProperty(p.Name), Expression.Property(source, p.Name)));&nbsp; &nbsp; var result = Expression.MemberInit(Expression.New(resultType), bindings);&nbsp; &nbsp; return Expression.Lambda<Func<TSource, dynamic>>(result, source);}

莫回无

我对如何在不使用Expressions. 很显然,因为Reflection在C#中是缓慢,因为在此进一步解释第二条,我决定用一个叫库FastMember去获得对象的属性。==============安装 FastMember在 PackageManagerConsole 中运行以下命令来安装库。Install-Package FastMember -Version 1.4.1写函数我们的函数/方法将成为任何泛型类型的扩展方法,例如TEntity,它必须是 aclass并且将字段数组作为参数告诉函数TEntity要返回哪些属性。using FastMember;using Dynamic;using System;using System.Linq;using System.Collections.Genericpublic static class Utilities{&nbsp; &nbsp; public static dynamic GetDynamicFields<TEntity>(this TEntity entity, params string[] fields)&nbsp; &nbsp; &nbsp; &nbsp; where TEntity : class&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; dynamic dynamic = new ExpandoObject();&nbsp; &nbsp; &nbsp; &nbsp; // ExpandoObject supports IDictionary so we can extend it like this&nbsp; &nbsp; &nbsp; &nbsp; IDictionary<string,object> dictionary = dynamic as IDictionary<string,object>;&nbsp; &nbsp; &nbsp; &nbsp; TypeAccessor typeAccessor = TypeAccessor.Create(typeof(TEntity));&nbsp; &nbsp; &nbsp; &nbsp; ObjectAccessor accessor = ObjectAccessor.Create(entity);&nbsp; &nbsp; &nbsp; &nbsp; IDictionary<string,Member> members = typeAccessor.GetMembers().ToDictionary(x => x.Name);&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < fields.Length; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (members.ContainsKey(fields[i]))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var prop = members[fields[i]];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (dictionary.ContainsKey(prop.Name))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dictionary[prop.Name] = accessor[prop.Name];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dictionary.Add(prop.Name, accessor[prop.Name]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return dynamic;&nbsp; &nbsp; }}如何使用使用该方法很简单,可以这样做:Message msg = new Message();dynamic result = msg.GetDynamicFields("Id","Text");在 c# 中,dynamic是ExpandoObject. 在查看代码后,ExpandoObject我意识到它实现了IDictionary<string,object>. 因此,这意味着我们可以扩展它并在运行时向它添加动态属性,从而使我们更容易。测试用例时间使用NUnit在上述方法上运行测试用例大约需要 40毫秒,这听起来足够好。希望此解决方案对您有用,或者可能为您提供有关如何解决问题的想法。
打开App,查看更多内容
随时随地看视频慕课网APP