2011-02-07 10 views
15

मैं एक ऑब्जेक्ट लौटने वाले अभिव्यक्ति वृक्ष का उपयोग करके एक विधि बनाने की कोशिश कर रहा हूं, लेकिन मैं यह समझ नहीं सकता कि वास्तव में वस्तु को वापस करने के लिए कैसे निर्दिष्ट करें। मैंने this पढ़ने की कोशिश की है, लेकिन वापसी मूल्य वास्तव में कहीं भी निर्दिष्ट नहीं होता है।अभिव्यक्ति वृक्ष विधि से वापस आने के लिए ऑब्जेक्ट को मैं कैसे निर्दिष्ट करूं?

मुझे सभी असाइनमेंट & सामान मिल गया है, लेकिन मैं अभिव्यक्ति पेड़ का उपयोग करके बनाई गई विधि से वापस आने के लिए ऑब्जेक्ट को कैसे निर्दिष्ट करूं?

संपादित करें: इन v4 अभिव्यक्ति पेड़ हैं, और विधि मैं बनाने के लिए कोशिश कर रहा हूँ कुछ इस तरह है:

private object ReadStruct(BinaryReader reader) { 
    StructType obj = new StructType(); 
    obj.Field1 = reader.ReadSomething(); 
    obj.Field2 = reader.ReadSomething(); 
    //...more... 
    return obj; 
} 
+0

चूंकि यह वास्तव में एक फर्क पड़ता है, क्या ये v3 या v4 अभिव्यक्ति पेड़ हैं? साथ ही, क्या आप उस कोड का उदाहरण दिखा सकते हैं जिसे आप पेड़ के साथ प्रस्तुत करने की कोशिश कर रहे हैं? –

+0

v4 अभिव्यक्ति पेड़। कोड जोड़ने के लिए संपादित किया गया। – thecoop

उत्तर

18

जाहिर है एक return एक GotoExpression कि आप Expression.Return कारखाने विधि के साथ बना सकते हैं। आपको कूदने के लिए अंत में एक लेबल बनाना होगा। कुछ ऐसा:

// an expression representing the obj variable 
ParameterExpression objExpression = ...; 

LabelTarget returnTarget = Expression.Label(typeof(StructType)); 

GotoExpression returnExpression = Expression.Return(returnTarget, 
    objExpression, typeof(StructType)); 

LabelExpression returnLabel = Expression.Label(returnTarget, defaultValue); 

BlockExpression block = Expression.Block(
    /* ... variables, all the other lines and... */, 
    returnExpression, 
    returnLabel); 

लेबल लक्ष्य और गोटो अभिव्यक्ति के प्रकार मेल खाना चाहिए। चूंकि लेबल लक्ष्य में एक प्रकार है, लेबल अभिव्यक्ति का डिफ़ॉल्ट मान होना चाहिए।

+1

'लेबल' तर्क कहां इंगित करता है? – thecoop

+2

@thecoop: कुछ अन्य चीजों को बदलना पड़ा, लेकिन मुझे यह काम मिल गया। यह सुनिश्चित करने के लिए यह सुनिश्चित करने में बहुत परेशानी है! –

+2

Ay, यह काम करता है। कोई विचार क्यों यह इतना गड़बड़ है? – thecoop

11

मुझे कुछ स्रोत मिल गए हैं जो एक (एक मामला) या वास्तव में राज्य (एक और मामला) है जो अभिव्यक्ति से मूल्य लौटाता है, केवल पैरामीटर अभिव्यक्ति के साथ ब्लॉक को समाप्त करके किया जा सकता है जो प्रश्न में मूल्य के अनुरूप है , चूंकि ब्लॉक से अंतिम मूल्यवान अभिव्यक्ति इसकी वापसी मान बन जाती है। रिपोर्ट के अनुसार, अभिव्यक्ति। वापसी कारखाना अधिक जटिल मामलों के लिए मौजूद है जहां एक कोड के ब्लॉक के बीच से आता है।

दूसरे शब्दों में, यदि आपके ब्लॉक के अंदर अंतिम अभिव्यक्ति बस objExpression थी, तो यह पर्याप्त होना चाहिए। मुझे लगता है, अगर आप रिटर्न विधि और लेबल के साथ उस व्यवसाय को रद्द कर देते हैं, तो वास्तव में जो होता है वह है objExpression मूल रूप से लेबल (ब्लॉक के अंत में) को वितरित किया जाता है और वहां छोड़ दिया जाता है, यदि आप वापसी को हटा देते हैं तो एक्सेप्शन और वापसी लेबल और बस objExpression के साथ निष्कर्ष निकाला।

दुर्भाग्य से, मैं वास्तव में इस परीक्षण का परीक्षण करने की स्थिति में नहीं हूं।

+4

.NET 4.5 – bugventure

+0

में सत्यापित है .NET 4 में मेरे लिए काम करता है। ब्लॉक अभिव्यक्ति के अंत में शून्य अभिव्यक्ति के अंत में केवल 'अभिव्यक्ति। कॉन्स्टेंट (शून्य) '। –

22

ऐसे मामलों में ऐसा करने का एक आसान तरीका है जो मौजूदा पैरामीटर या चर लौटाता है। ब्लॉक अभिव्यक्ति में अंतिम बयान वापसी मूल्य बन जाता है। आप इसे वापस लौटने के अंत में पैरामीटर एक्सप्रेशन को फिर से शामिल कर सकते हैं।

अपने struct मान लिया जाये कि इस तरह है:

public struct StructType 
{ 
    public byte Field1; 
    public short Field2; 
} 

फिर अपने कोड इस तरह दिखेगा:

var readerType = typeof(BinaryReader); 
var structType = typeof(StructType); 
var readerParam = Expression.Parameter(readerType); 
var structVar = Expression.Variable(structType); 

var expressions = new List<Expression>(); 

expressions.Add(
    Expression.Assign(
     Expression.MakeMemberAccess(structVar, structType.GetField("Field1")), 
     Expression.Call(readerParam, readerType.GetMethod("ReadByte")) 
     ) 
    ); 

expressions.Add(
    Expression.Assign(
     Expression.MakeMemberAccess(structVar, structType.GetField("Field2")), 
     Expression.Call(readerParam, readerType.GetMethod("ReadInt16")) 
     ) 
    ); 

expressions.Add(structVar); //This is the key. This will be the return value. 

var ReadStruct = Expression.Lambda<Func<BinaryReader, StructType>>(
    Expression.Block(new[] {structVar}, expressions), 
    readerParam).Compile(); 

टेस्ट है कि यह काम करता है:

var stream = new MemoryStream(new byte[] {0x57, 0x46, 0x07}); 
var reader = new BinaryReader(stream); 
var struct1 = ReadStruct(reader); 

यह इस उदाहरण उल्लेख के लायक है स्ट्रक्चर टाइप एक स्ट्रक्चर टाइप करता है। यदि यह एक वर्ग है, तो आप केवल कन्स्ट्रक्टर को कॉल करें और BlockExpression में structVar पहली चीज़ प्रारंभ करें।

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