2013-06-14 6 views
7

मैं अपने डेटा को क्रमबद्ध/deserialize करने के लिए protobuf-net का उपयोग करता हूं।प्रोटोबफ-नेट हैंडल रीडोनली फ़ील्ड कैसे करता है?

मेरे पास कुछ साधारण वर्ग हैं, इसलिए यह कोई वास्तविक समस्या नहीं है।

जहां तक ​​मुझे पता है, प्रोटोबफ-नेट आईआर पीढ़ी का उपयोग धारावाहिक/deserialization कोड बनाने के लिए करता है। जबकि मेरे पास मेरे मॉडल में केवल पढ़ने के क्षेत्र हैं, मुझे आश्चर्य है कि आईएल के साथ ऐसे क्षेत्र में लिखना संभव है? मैं स्पष्ट रूप से देख सकता हूं कि यह अच्छी तरह से काम करता है, लेकिन मुझे नहीं पता क्यों ...

मैंने इसे कोड में जासूसी करने की कोशिश की है, लेकिन यह थोड़ा जटिल है।

इस तरह के कोड को उत्पन्न करने के मेरे प्रयास हमेशा आईएल सत्यापनकर्ता त्रुटियों में परिणाम देते हैं।

उत्तर

7

असल में, मैं इसे विफल नहीं कर सकता - कम से कम, स्मृति में उत्पन्न करते समय।

चलो बस public readonly फ़ील्ड के साथ शुरू करें (इसलिए हम किसी भी एक्सेसबिलिटी नियमों को तोड़ नहीं रहे हैं); मेरा पहला प्रयास के रूप में नीचे है, और यह ठीक काम करता है:

private readonly int i; 

कोड तो ऊपर ओह-तो-अस्पष्ट देता है: यदि क्षेत्र private है

using System; 
using System.Reflection; 
using System.Reflection.Emit; 
class Foo 
{ 
    public readonly int i; 
    public int I { get { return i; } } 
    public Foo(int i) { this.i = i; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     var setter = CreateWriteAnyInt32Field(typeof(Foo), "i"); 
     var foo = new Foo(123); 
     setter(foo, 42); 
     Console.WriteLine(foo.I); // 42; 
    } 
    static Action<object, int> CreateWriteAnyInt32Field(Type type, string fieldName) 
    { 
     var field = type.GetField(fieldName, 
      BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 
     var method = new DynamicMethod("evil", null, 
      new[] { typeof(object), typeof(int) }); 
     var il = method.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Castclass, type); 
     il.Emit(OpCodes.Ldarg_1); 
     il.Emit(OpCodes.Stfld, field); 
     il.Emit(OpCodes.Ret); 
     return (Action<object, int>)method.CreateDelegate(typeof(Action<object, int>)); 
    } 
} 

केवल समय यह दिलचस्प हो जाता है है :

ऑपरेशन रनटाइम को अस्थिर कर सकता है।

var method = new DynamicMethod("evil", null, 
    new[] { typeof(object), typeof(int) }, field.DeclaringType); 

कुछ अन्य आंतरिक चेकों किया जा सकता है skipVisibility को सक्षम करने से:

लेकिन हम नाटक है कि विधि क्षेत्र के घोषित प्रकार के अंदर है द्वारा कि चारों ओर पाने के

var method = new DynamicMethod("evil", null, 
    new[] { typeof(object), typeof(int) }, field.DeclaringType, true); 

हालांकि, ध्यान दें कि स्टैंडअलोन असेंबली उत्पन्न करते समय यह सब संभव नहीं है। वास्तविक डीएलएस बनाते समय आपको बहुत अधिक मानकों पर रखा जाता है। इस कारण से, precompiler उपकरण (असेंबली प्री-जेनरेट करने के लिए) इन-मेमोरी मेटा-प्रोग्रामिंग कोड के परिदृश्यों की एक ही श्रृंखला को संभाल नहीं सकता है।

+0

मैं इसे तुरंत देखूंगा। हो सकता है कि मेरी समस्या सख्ती से पढ़ाई वाले क्षेत्रों से संबंधित न हो। मजाकिया बात यह है कि मेरा कोड मोनो पर काम करता है और .NET पर नहीं है। –

+0

दोह। मैं DeclaringType प्रदान करने में विफल रहा। लेकिन अब मुझे आश्चर्य है - यह क्यों काम करता है? क्या एक पाठक क्षेत्र केवल वस्तु के निर्माता से लिखने योग्य नहीं होना चाहिए? एक जवाब के लिए धन्यवाद, वैसे भी। –

+0

@PiotrZierhoffer कई चीजें केवल कंपाइलर पर लागू होती हैं, और पूरी तरह से 'PEVerify' में। आखिरकार, आप प्रतिबिंब के माध्यम से 'रीडोनली' फ़ील्ड बदल सकते हैं, और सीरियलाइजर्स/कटाइज़र अक्सर ** पूरी तरह से ** कन्स्ट्रक्टर को छोड़ सकते हैं, इसलिए अगर ऐसा होता तो –

3

जैसा कि मुझे इस चर्चा में काफी दिलचस्पी है, मैंने मार्क ग्रेवेल के उदाहरण कोड की कोशिश की है और ... यह एमएस .NET 4.0 पर VerificationException फेंकता है।

मैं इसे काम करने के लिए प्रबंधित किया है, लेकिन मैं owner पैरामीटर भी सार्वजनिक i क्षेत्र के मामले में field.DeclaringType करने के लिए सेट के साथ DynamicMethod निर्माता का उपयोग करने की जरूरत है। इस मामले में SkipVisibility पैरामीटर अनावश्यक प्रतीत होता है।

पीएस। मेरा मानना ​​है कि यह प्रविष्टि एक टिप्पणी होनी चाहिए, लेकिन प्रतिनिधि की कमी के कारण मैं दूसरों के उत्तरों पर टिप्पणी करने में असमर्थ हूं।

+0

ठीक है, मैंने मार्क का कोड नहीं चलाया है, केवल इसका विश्लेषण किया है, लेकिन यह बिंदु मान्य प्रतीत होता है। –

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