विभिन्न एसओ पदों से जानकारी का उपयोग करना और विशेष रूप से blog (के बजाय AndAlso
का उपयोग करने के लिए संशोधित) मैंने समान टाइप किए गए लिनक्स अभिव्यक्तियों को एक ही पूर्वानुमान में संयोजित करने में कामयाब रहा है। लेकिन अब मैं दो अभिव्यक्तियों को जोड़ना चाहता हूं जहां एक दूसरे के लिए इनपुट है। यहां पूरी तरह से विस्तारित मूल Expression
है;दो लिंक अभिव्यक्तियों का संयोजन
private Expression<Func<T, bool>> ExpressionIsNamed(IEnumerable<EntityName> AccessorNames)
{
// works
Expression<Func<T, bool>> Texpr = x => x.Security.Readers.Any(n => AccessorNames.ToStringArray().Contains(n.Text));
return Texpr;
}
ध्यान दें कि महत्वपूर्ण है, मैं इन के रूप में भाव) गठबंधन करने के लिए क्योंकि मेरी डीबी चालक पेड़ चलना और एक देशी कॉल तो संकलित (का उपयोग कर में तब्दील करने की जरूरत है प्रबंधन करने की आवश्यकता एक विकल्प नहीं है।
तो नीचे दिया गया फ़ंक्शन मैं ऊपर Any()
कॉल के साथ गठबंधन करना चाहता हूं। अंतिम आउटपुट अभिव्यक्ति को Expression<Func<T, bool>>
टाइप करने की आवश्यकता है और मुझे इस में x.Security.Readers
पास करने की आवश्यकता है।
public static Expression<Func<IEnumerable<EntityName>,bool>> AccessCheckExpression(IEnumerable<EntityName> AccessorNames)
{
return accessList => accessList.Any(n => AccessorNames.ToStringArray().Contains(n.Text));
}
मैं जहाँ तक इस रूप में मिल गया है, लेकिन मैं बाहर काम accessCheck
से बाहर accessList =>
स्वैप करने के लिए कैसे और यह एक एकल अभिव्यक्ति में accessList
का उपयोग किया है के लिए संघर्ष कर रहा हूँ। अब तक, मेरे पास यह है;
private Expression<Func<T, bool>> ExpressionIsNamed(IEnumerable<EntityName> AccessorNames)
{
Expression<Func<T, IEnumerable<EntityName>>> accessList = (T x) => x.Security.Readers;
Expression<Func<IEnumerable<EntityName>, bool>> accessCheck = SecurityDescriptor.AccessCheckExpression(AccessorNames);
// Combine?
Expression<Func<T, bool>> Texpr = ??? accessCheck + accessList ???
return Texpr;
}
[अपडेट]
तो मैं थोड़ा आगे मिल गया है;
class ParameterUpdateVisitor : System.Linq.Expressions.ExpressionVisitor
{
private ParameterExpression _oldParameter;
private ParameterExpression _newParameter;
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (object.ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
static Expression<Func<T, bool>> UpdateParameter<T>(
Expression<Func<T, IEnumerable<EntityName>>> expr,
ParameterExpression newParameter)
{
var visitor = new ParameterUpdateVisitor(expr.Parameters[0], newParameter);
var body = visitor.Visit(expr.Body);
return Expression.Lambda<Func<T, bool>>(body, newParameter);
}
मैं तब संकलित कर सकता हूं;
UpdateParameter(accessList, accessCheck.Parameters[0]);
उन Invoke()
सुझाव के लिए सभी को धन्यवाद, लेकिन मेरा अनुमान है कि जब भी MongoDB ड्राइवर को पाने से यह InvocationExpression
पसंद नहीं करेंगे। हालांकि, Invoke
और अब मेरा कोड ठीक उसी तरह विफल रहता है। अर्थात्;
System.ArgumentException: Expression of type
'System.Func`2[MyLib.Project,System.Collections.Generic.IEnumerable`1[MyLib.EntityName]]'
cannot be used for parameter of type
'System.Collections.Generic.IEnumerable`1[MyLib.EntityName]'
तो यह लगता है कि अंतर्निहित पैरामीटर x.Security.Readers
एक सादे पुराने IEnumerable<EntityName>
आपने 'ExpressionIsNamed' परिभाषा में टाइप पैरामीटर छोड़ा। –
@ हैमलेट हाकोबियन: जरूरी नहीं। वे जेनेरिक पैरामीटर को इस निजी विधि वाले वर्ग पर परिभाषित किया जा सकता है। –
@DanielHilgarth ठीक है। धन्यवाद! –