2013-08-09 6 views
5

मैं एक ऐसा करने पर काम कर रहा हूं। ढूँढें (ऑब्जेक्ट्स [] कुंजी) विधि जो डेटाबेस को क्वेरी करने के लिए गतिशील रूप से लैम्ब्डा फ़ंक्शन बनाता है।मैं एक Func <object [], अभिव्यक्ति <Func<T,bool> >> गतिशील कैसे कर सकता हूं?

असल में मैं क्या चाहते हैं:

var mykeys = new Guid("37ec1659-b35e-46c9-a7fc-e9802644ca1a"); 
IQueryable<T> database ; 
Func<object[],Expression<Func<T,bool>>> objectFinder = CreateKeyExpression(typeof(T)); 
var foundObject = database.FirstOrDefault(objectFinder(mykeys)); 

और

private LambdaExpression CreateKeyExpression(Type C1Type) 
{ 

    ParameterExpression instanceParameter = Expression.Parameter(C1Type); 
    ParameterExpression keyParameters = Expression.Parameter(typeof(object[])); 

    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray(); 
    var expr = Expression.Equal(Expression.TypeAs(Expression.Property(instanceParameter,objectKeys[0]),typeof(object)), 
     Expression.ArrayIndex(keyParameters,Expression.Constant(0))); 


    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter,objectKeys[i]), 
      Expression.ArrayIndex(keyParameters,Expression.Constant(i)) 
      )); 

    } 

    var lmp= Expression.Lambda(expr, instanceParameter); 

    return Expression.Lambda(lmp, keyParameters); 
} 

मैं यह कैसे प्राप्त कर सकते हैं की कोई भी विचार? उपर्युक्त मुझे Func<object[],Func<T,bool>> देता है, जो IQueryable को IQueryumerable बनाता है, जिसका अर्थ है कि यह डेटाबेस अंत में नहीं करेगा।

उत्तर

2

आप Expression.ArrayIndex के बजाय Expression.Constant विधि का उपयोग करने, क्योंकि आप कुंजी मान FirstOrDefault विधि का उपयोग कर के साथ अपने अभिव्यक्ति सरणी के लिए पारित करने के लिए सक्षम नहीं होगा की जरूरत है।

private static LambdaExpression CreateKeyExpression(Type C1Type, object[] parameters) 
{ 
    var instanceParameter = Expression.Parameter(C1Type); 
    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray(); 

    var expr = Expression.Equal(Expression.Property(instanceParameter, objectKeys[0]), 
     Expression.Constant(parameters[0], objectKeys[0].PropertyType)); 


    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter, objectKeys[i]), 
      Expression.Constant(parameters[i], objectKeys[i].PropertyType))); 
    } 
    return Expression.Lambda(expr, instanceParameter); 
} 

var parameters = new object[] { Guid.NewGuid(), Guid.NewGuid() }; 
var lambdaExpression = CreateKeyExpression(typeof(TestClass), parameters); 
var testClasses = new List<TestClass>() { new TestClass { Id = (Guid)parameters[0], Id1 = (Guid)parameters[1] } }; 
var testClass = testClasses.AsQueryable().FirstOrDefault((Expression<Func<TestClass, bool>>)lambdaExpression); 
+0

दिलचस्प, मैं इसे थोड़ा अलग हल किया। CreateKeyExpression में ऑब्जेक्ट [] पैरामीटर डालना एक विकल्प नहीं था। मैं किसी दिए गए सी 1 टाइप के लिए अभिव्यक्ति को कैश करने में सक्षम होना चाहता था क्योंकि मैंने एक Func > क्यों पूछा। जो मुझे हर प्रकार के लिए इसे कैश करने देगा और इसे हर बार उत्पन्न करने के लिए चाबियों का एक नया सेट उपयोग नहीं करेगा। अगर मैं इसे चाहता हूं तो मैं अपना समाधान भी पोस्ट करूंगा। धन्यवाद –

0
private Expression<Func<object[], Expression<Func<C1Source, bool>>>> CreateKeyExpression<C1Source>() 
{ 

    ParameterExpression instanceParameter = Expression.Parameter(typeof(C1Source)); 
    ParameterExpression keyParameters = Expression.Parameter(typeof(object[])); 

    PropertyInfo[] objectKeys = typeof(C1Source).GetKeyProperties().ToArray(); 
    var expr = Expression.Equal(Expression.Property(instanceParameter,objectKeys[0]), 
    Expression.Convert( 
     Expression.ArrayIndex(keyParameters,Expression.Constant(0)), 
     objectKeys[0].PropertyType) 
     ); 

    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter,objectKeys[i]), 
      Expression.Convert(
       Expression.ArrayIndex(keyParameters,Expression.Constant(i)), 
       objectKeys[i].PropertyType) 
       ); 

    } 

    var lmp= Expression.Lambda(expr, instanceParameter); 

    return Expression.Lambda<Func<object[], Expression<Func<C1Source, bool>>>>(lmp, keyParameters); 

} 
संबंधित मुद्दे