2013-01-11 12 views
7

जैसे लैम्ब्डा अभिव्यक्ति बनाने के लिए प्रतिबिंब का उपयोग करें मेरे पास IQuerable<object> source ऑब्जेक्ट है और इसे इस तरह से प्राप्त करना है (लेकिन प्रतिबिंब का उपयोग करना)।x => new {..}

source.Select(t => new SelectListItem { Name = t.Name, Value = t.Id }) 

मैं यह कैसे कर सकता हूं, या मुझे उस तरह के अभिव्यक्ति वृक्ष के निर्माण के संदर्भ कहां मिल सकते हैं।

धन्यवाद

+0

यदि आप जानते हैं कि आप किस प्रकार का उपयोग कर सकते हैं तो आप गणना कर सकते हैं। कैस्ट: http://msdn.microsoft.com/en-us/library/bb341406.aspx –

+0

क्या यह तत्वों को 'गतिशील' में डालने का विकल्प होगा? – Douglas

+0

गतिशील प्रतिबिंब से बेहतर विकल्प लगता है। यह प्रतिबिंब का उपयोग करने के लिए काफी अजीब लग रहा है। क्या आप ऐसा कुछ नहीं कर सकते जो इंटरफेस के अनुरूप INameValuePair जैसा हो? – mathk

उत्तर

12

आप ExpressionSystem.Linq.Expressions नाम स्थान (MSDN)

आपके मामले में उपयोग करते हुए है, यह कुछ इस तरह दिखेगा बना सकते हैं:

var source = typeof(Source); 
var target = typeof(SelectListItem); 

var t = Expression.Parameter(source, "t"); 

var sourceName = Expression.MakeMemberAccess(t, source.GetProperty("Name")); 
var sourceId = Expression.MakeMemberAccess(t, source.GetProperty("Id")); 

var assignName = Expression.Bind(target.GetProperty("Name"), sourceName); 
var assignValue = Expression.Bind(target.GetProperty("Value"), sourceId); 
var targetNew = Expression.New(target); 
var init = Expression.MemberInit(targetNew, assignName, assignValue); 

var lambda = 
    (Expression<Func<Source,SelectListItem>>) Expression.Lambda(init, t); 

, जिसे आप इस तरह इसका इस्तेमाल कर सकते :

IQueryable<Source> list = ... 

List<SelectListItem> items = list.Select(lambda).ToList(); 
0

रनटाइम के दौरान किस प्रकार की जानकारी (यदि कोई है) के बारे में यह थोड़ा अस्पष्ट है। पर पिग्गीबैकिंग निकोलस बटलर का उत्तर (चूंकि इसे स्वीकार कर लिया गया है) मान लीजिए कि आप स्रोत प्रकार (यानी IQueryable स्रोत में टी का प्रकार क्या है) "को जान लेंगे और आप लक्ष्य प्रकार (आइटम प्रकार लौटाएंगे) IQueryable से एक्सटेंशन एक्सटेंशन का चयन करें)। जब मैं "जानता हूं" कहता हूं, मेरा मतलब है कि यह कुछ ऐसा है जिसे बिना गतिशीलता, प्रतिबिंब, देर से बाध्यकारी आदि के रनटाइम पर खोजा जा सकता है अन्यथा उसका समाधान केवल तभी काम करेगा जब स्रोत और लक्ष्य प्रकारों में उन मिलान करने वाले नामों के साथ गुण हों (यानी "नाम/आईडी" & "नाम/मूल्य")।

यह देखते हुए, वहाँ मैन्युअल रूप से अपने लैम्ब्डा अभिव्यक्ति का निर्माण करने के बिना एक बहुत सरल उपाय है ...

समाधान: पहले इन 2 प्रकार सिर्फ इसलिए हम जानते हैं कि हम क्या साथ काम कर रहे परिभाषित करने देता है। मैं केवल ऐसा करते हैं क्योंकि मैं क्या प्रकार के प्रयोग कर रहे हैं पता नहीं है, इसलिए इन वास्तव में क्या आप वास्तव में उपयोग कर रहे हैं के लिए प्लेसहोल्डर हैं, तो यह आपके समाधान के लिए की जरूरत नहीं है, बस डेमो/उदाहरण के प्रयोजनों के लिए:

//this is whatever your source item type is (t) 
public class NameIdPair 
{ 
    public string Name { get; set; } 

    public string Id { get; set; } 
} 

//this is whatever the SelectListItem type is you're using 
public class SelectListItem 
{ 
    public string Name { get; set; } 

    public string Value { get; set; } 
} 

अगला 2 विधियों के साथ एक साधारण स्थैतिक वर्ग को परिभाषित करने देता है। एक विधि लैम्ब्डा अभिव्यक्ति का निर्माण करेगा और अन्य विधि बदलने और IEnumerable में स्रोत (IQueryable) का चयन करेंगे:

public static class QueryableExtensions 
{ 
    public static IEnumerable<TItem> Select<TSource, TItem>(this IQueryable<TSource> source) 
     where TSource : NameIdPair 
     where TItem : SelectListItem, new() 
    { 
     if (source == null) throw new ArgumentNullException("source"); 

     return source.Select(CreateLambda<TSource, TItem>()); 
    } 

    public static Expression<Func<TSource, TItem>> CreateLambda<TSource, TItem>() 
     where TSource : NameIdPair 
     where TItem : SelectListItem, new() 
    { 

     return (t) => new TItem { Name = t.Name, Value = t.Id }; 
    } 
} 

उपयोग:

//create an instance of an IQueryable<T> for demo purposes 
var source = new[] 
{ 
    new NameIdPair {Name = "test1_name", Id = "test1_Id"}, 
    new NameIdPair {Name = "test2_name", Id = "test2_Id"} 
}.AsQueryable(); 

//you can call the "Select" extension method to select the queryable into an enum. 
var enumerable = source.Select<NameIdPair, SelectListItem>(); 
//'enumerable' is an IEnumerable<SelectListItem> instance 

//or if you just want the lambda expression... 
var lambda = QueryableExtensions.CreateLambda<NameIdPair, SelectListItem>(); 

//lambda.ToString() returns "t => new SelectListItem() {Name = t.Name, Value = t.Id}"; 
तो वहाँ तुम जाओ

। सुनिश्चित नहीं है कि यह वही है जो आप खोज रहे हैं, या यदि यह आपकी आवश्यकताओं के अनुरूप है। उम्मीद है कि किसी को यह उपयोगी लगेगा।

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