TL; DR:閱讀第1點的示例。使用QueryMap中的代碼,使更改以粗體顯示在下面。
對,我已經成功地解決此使用一些很小的改動就QueryMap
有兩件事情我需要得到工作:
圖如何告訴querymap調用使用數據上下文的方法?
圖如何獲得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
在這種情況下)正常其他論點。
第二部分然而需要一些(相當輕微)變化爲MappedQueryVisitor.cs
。在這兩種情況下只有一個if語句(裏面有語句!)。
替換現有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;
}