2 回答
TA贡献1775条经验 获得超8个赞
不能直接投影到ExpandoObject/ dynamic。
但是您可以在运行时投影到动态创建的类型。参见例如Microsoft.EntityFrameworkCore.DynamicLinq包 - 动态数据类。
如果您以 nuget 的形式安装该软件包(您可以自己开发类似的功能,但您应该基本上实现该软件包的所有功能),则可以按如下方式实现该方法:
using System.Linq.Dynamic.Core;
static Expression<Func<TSource, dynamic>> DynamicFields<TSource>(IEnumerable<string> fields)
{
var source = Expression.Parameter(typeof(TSource), "o");
var properties = fields
.Select(f => typeof(TSource).GetProperty(f))
.Select(p => new DynamicProperty(p.Name, p.PropertyType))
.ToList();
var resultType = DynamicClassFactory.CreateType(properties, false);
var bindings = properties.Select(p => Expression.Bind(resultType.GetProperty(p.Name), Expression.Property(source, p.Name)));
var result = Expression.MemberInit(Expression.New(resultType), bindings);
return Expression.Lambda<Func<TSource, dynamic>>(result, source);
}
TA贡献1865条经验 获得超7个赞
我对如何在不使用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.Generic
public static class Utilities
{
public static dynamic GetDynamicFields<TEntity>(this TEntity entity, params string[] fields)
where TEntity : class
{
dynamic dynamic = new ExpandoObject();
// ExpandoObject supports IDictionary so we can extend it like this
IDictionary<string,object> dictionary = dynamic as IDictionary<string,object>;
TypeAccessor typeAccessor = TypeAccessor.Create(typeof(TEntity));
ObjectAccessor accessor = ObjectAccessor.Create(entity);
IDictionary<string,Member> members = typeAccessor.GetMembers().ToDictionary(x => x.Name);
for (int i = 0; i < fields.Length; i++)
{
if (members.ContainsKey(fields[i]))
{
var prop = members[fields[i]];
if (dictionary.ContainsKey(prop.Name))
dictionary[prop.Name] = accessor[prop.Name];
else
dictionary.Add(prop.Name, accessor[prop.Name]);
}
}
return dynamic;
}
}
如何使用
使用该方法很简单,可以这样做:
Message msg = new Message();
dynamic result = msg.GetDynamicFields("Id","Text");
在 c# 中,dynamic是ExpandoObject. 在查看代码后,ExpandoObject我意识到它实现了IDictionary<string,object>. 因此,这意味着我们可以扩展它并在运行时向它添加动态属性,从而使我们更容易。
测试用例时间
使用NUnit在上述方法上运行测试用例大约需要 40毫秒,这听起来足够好。
希望此解决方案对您有用,或者可能为您提供有关如何解决问题的想法。
- 2 回答
- 0 关注
- 231 浏览
添加回答
举报