以下は、MemberInitExpression を使用した彼のソリューションで説明されている "usr" の肉付けされた例です。
私の解決策として、式の結果を書き込む新しいクラスを提供します。実際には、これはエンティティ自体の POCO である可能性がありますが、別のクラスを指定することで、投影元のクラスと比較して、投影先のクラスがどのクラスであるかが明確になります。「usr」が述べたように、Tuple やその他の構造を使用することもできます。私の現在のお気に入りは、最後に追加した追加のコードを使用して新しい型を動的に作成することです。これは Tuple よりも少し柔軟性がありますが、ほとんどの部分でリフレクションがアクセスする必要があるという点で、いくつかの欠点があります。
射影するクラス:
public class Holder
{
public int Item1{ get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
式を作成するコード:
ParameterExpression paramExp = Expression.Parameter(typeof(AnEntity));
NewExpression newHolder = Expression.New(typeof(Holder));
Type anonType = typeof(Holder);
MemberInfo item1Member = anonType.GetMember("Item1")[0];
MemberInfo item2Member = anonType.GetMember("Item2")[0];
MemberInfo item3Member = anonType.GetMember("Item3")[0];
// Create a MemberBinding object for each member
// that you want to initialize.
MemberBinding item1MemberBinding =
Expression.Bind(
item1Member,
Expression.PropertyOrField(paramExp, "prop1"));
MemberBinding item2MemberBinding =
Expression.Bind(
item2Member,
Expression.PropertyOrField(paramExp, "prop2"));
MemberBinding item3MemberBinding =
Expression.Bind(
item3Member,
Expression.PropertyOrField(paramExp, "prop3"));
// Create a MemberInitExpression that represents initializing
// two members of the 'Animal' class.
MemberInitExpression memberInitExpression =
Expression.MemberInit(
newHolder,
item1MemberBinding,
item2MemberBinding,
item3MemberBinding);
var lambda = Expression.Lambda<Func<AnEntity, Holder>>(memberInitExpression, paramExp);
最後に、式をどのように呼び出すか:
IQueryable<AnEntity> myEntities = dbContext.MyEntities.AsQueryable();
var results = myEntities.Select(selectLambda);
戻り値の型を動的に定義する場合の追加コードを次に示します。
public static Type CreateNewType(string assemblyName, string typeName, params Type[] types)
{
// Let's start by creating a new assembly
AssemblyName dynamicAssemblyName = new AssemblyName(assemblyName);
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule(assemblyName);
// Now let's build a new type
TypeBuilder dynamicAnonymousType = dynamicModule.DefineType(typeName, TypeAttributes.Public);
// Let's add some fields to the type.
int itemNo = 1;
foreach (Type type in types)
{
dynamicAnonymousType.DefineField("Item" + itemNo++, type, FieldAttributes.Public);
}
// Return the type to the caller
return dynamicAnonymousType.CreateType();
}