3
我试图建立一个表达式与泛型类型参数个数可变创建通用Tuple<>
实例变量数量的元组。表达对创建的泛型类型参数
生成的Tuple<>
实例的想法是基于其上具有KeyAttribute
的属性为实体类型动态创建组合键值。然后组合键将被用作Dictionary<object, TEntity>
中的键。所以lambda表达式应该建立一定的实体类型和拉姆达会被调用,传递的TEntity
一个实例来取回一个Tuple<>
形式的组合键。
例实体模型
public class MyEntityModel
{
[Key]
public string Key1 { get; set; }
[Key]
public Guid Key2 { get; set; }
public int OtherProperty { get; set; }
}
表达什么应该做
public Func<MyEntityModel, object> BuildKeyFactory()
{
// This is how the LambdaExpression should look like, but then for a generic entity type instead of fixed to MyEntityModel
return new Func<MyEntityModel, object>(entity => new Tuple<string, Guid>(entity.Key1, entity.Key2));
}
但当然的实体模型需要一个泛型类型。
我有什么到目前为止
public Func<TEntity, object> BuildKeyFactory<TEntity>()
{
var entityType = typeof(TEntity);
// Get properties that have the [Key] attribute
var keyProperties = entityType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(x => x.GetCustomAttribute(typeof(KeyAttribute)) != null)
.ToArray();
var tupleType = Type.GetType($"System.Tuple`{keyProperties.Length}");
if (tupleType == null) throw new InvalidOperationException($"No tuple type found for {keyProperties.Length} generic arguments");
var keyPropertyTypes = keyProperties.Select(x => x.PropertyType).ToArray();
var tupleConstructor = tupleType.MakeGenericType(keyPropertyTypes).GetConstructor(keyPropertyTypes);
if (tupleConstructor == null) throw new InvalidOperationException($"No tuple constructor found for key in {entityType.Name} entity");
// The following part is where I need some help with...
var newTupleExpression = Expression.New(tupleConstructor, keyProperties.Select(x => ????));
return Expression.Lambda<Func<TEntity, object>>(????).Compile();
}
正如你所看到的,我无法弄清楚如何我需要为传递给Expression.New()
调用(可能是一些与Expression.MakeMemberAccess(Expression.Property())
创建属性表达式,但不知道如何从lambda参数中传递TEntity
实例),以及如何通过Expression.Lambda
调用将其链接起来。任何帮助将不胜感激!