TL;DR : ポイント 1 の例を読んでください。QueryMap のコードを使用して、以下の太字の部分を変更してください。
そうですね、 QueryMapに若干の変更を加えることで、この問題を回避できました。
私が仕事をするために必要な2つのことがありました:
データ コンテキストを使用するメソッドを呼び出すように querymap に指示する方法がわかりましたか?
インターフェイスを介してアクセスされたときに、クラスで定義された属性を取得するためにクエリマップを取得する方法を理解してください。
最初の部分はかなり単純でした:
private static readonly ExpressionMethod<Func<AquaReportsRepository, string, bool>> _IsPhysicalItem =
ExpressionMethod.Create((AquaReportsRepository ardc, string i) => ardc._AquaReportsDC.Aqua_IsPhysicalItem(i) ?? true);
[MapToExpression("_IsPhysicalItem")]
public bool IsPhysicalItem(string itemNumber)
{
return _IsPhysicalItem.Invoke(this, itemNumber);
}
ここで重要なのはAquaReportsRepository
、通常の他の引数に加えて、オブジェクト自体を最初の引数 (この場合) として受け取る関数を使用することです。
ただし、2 番目の部分では、 にいくつかの (かなりマイナーな) 変更が必要でしたMappedQueryVisitor.cs
。どちらの場合も、if ステートメントは 1 つだけです (内部にステートメントがあります!)。
既存のGetLambda
メソッドを次のように置き換えます。
private LambdaExpression GetLambda(Expression receiver, MemberInfo member) {
LambdaExpression exp;
if(!_mappings.TryGetValue(member, out exp)) {
exp = _mappingLookup(member);
if(null == exp) {
var attr = (MapToExpressionAttribute) member.GetCustomAttributes(typeof(MapToExpressionAttribute), true).FirstOrDefault();
// Added by me to deal with interfaces
if (null == attr)
{
if (null != receiver)
{
// member could be an interface's member, so check the receiver.object type
if (receiver.NodeType == ExpressionType.Constant)
{
var receiverType = ((ConstantExpression)receiver).Value.GetType();
var receiverMemberInfo = receiverType.GetMembers().Where(mi => mi.Name == member.Name).SingleOrDefault();
if (null != receiverMemberInfo)
{
attr = (MapToExpressionAttribute)receiverMemberInfo.GetCustomAttributes(typeof(MapToExpressionAttribute), true).FirstOrDefault();
member = receiverMemberInfo;
}
}
}
}
if(null != attr) {
exp = GetLambdaFromAttribute(receiver, member.DeclaringType, attr);
}
}
_mappings.Add(member, exp);
}
return exp;
}
この変更はmember
MethodInfo
、インターフェイス メソッドを表すオブジェクトがある場合、それを認識し、MethodInfo
使用している具体的な型 (定数式で定義) の実際の値を取得しようとすることを意味します。
インターフェイスの をMapToExpressionAttribute
指定すると、実装クラスの属性が正しく取得されるようになりました。MemberInfo
ただし、次の問題は ですVisitMethodCall
。属性から呼び出す置換式を取得すると、引数式がインターフェイス タイプであるため、呼び出しているメソッドによって実装クラスが必要になるため、失敗します。
この最後のコード変更はそれを修正します。
CollectArguments
メソッドを次のように変更します。
private static IEnumerable<Expression> CollectArguments(MethodCallExpression m) {
IEnumerable<Expression> args = m.Arguments;
if (!m.Method.IsStatic)
{
var objectExpression = m.Object;
// Added by me, to deal with interfaces
if (objectExpression.NodeType == ExpressionType.Constant)
{
var objectConstExpression = ((ConstantExpression)objectExpression);
if (objectConstExpression.Type.IsInterface)
{
objectExpression = Expression.Constant(objectConstExpression.Value);
}
}
args = Enumerable.Repeat(objectExpression, 1).Concat(args);
}
return args;
}