2010-08-04 11 views
8

मैं अपने नियमित .NET 3.5 एप्लिकेशन से सेवा के रूप में मोनो के कंपाइलर का उपभोग करना चाहता हूं।एक सेवा के रूप में मोनो कंपाइलर (एमसीएस)

मैंने नवीनतम बिट्स (2.6.7) डाउनलोड किए हैं, विजुअल स्टूडियो में एक सरल कंसोल एप्लिकेशन बनाया है और मोनो.एससीएचआरपी डीएल का संदर्भ दिया है।

फिर, मेरे कंसोल अनुप्रयोग में (सीधे एक नमूना से बाहर ऑनलाइन):

Illegal enum value: 2049. 
Parameter name: access 

इसका कारण यह है है:

Evaluator.Run("using System; using System.Linq;"); 
    bool ress; 
    object res; 
    Evaluator.Evaluate(
     "from x in System.IO.Directory.GetFiles (\"C:\\\") select x;", 
     out res, out ress); 

    foreach (var v in (IEnumerable)res) 
    { 
     Console.Write(v); 
     Console.Write(' '); 
    } 

यह Evaluator.Run में एक अपवाद (पहली पंक्ति) फेंकता डीएल को Mono.exe का उपयोग करके संकलित किया गया था, csc.exe नहीं, मुझे विश्वास है।

मैंने डेमो-repl.zip फ़ाइल में सीधे http://tirania.org/blog/archive/2010/Apr-27.html से मोनो.CSharp डीएल डाउनलोड करने का प्रयास किया है ... और यह अपवाद नहीं फेंकता है ... हालांकि Evaluator को कॉल करने के बाद बाहर पैरामीटर (res)। मूल्यांकन करें शून्य है ... तो मुझे यकीन नहीं है कि क्या गलत हो रहा है। कोई अपवाद फेंक दिया गया है ...

तो, मैं यह जानना चाहता हूं कि डेमो-repl.zip से डाउनलोड किया गया डीएलएल शून्य क्यों देता है।

संपादित करें: मुझे पता चला कि यह शून्य क्यों लौटाता है। ऐसा लगता है कि संकलक सिस्टम को नहीं उठा रहा है। लिंक्स नेमस्पेस ... हालांकि मैं यह नहीं बता सकता कि क्यों ... अगर मैं सिर्फ "System.IO.Directory.GetFiles (\" C: \\ का मूल्यांकन करता हूं ")", यह बढ़िया काम करता है।

अपडेट: यह निश्चित रूप से ऐसा लगता है कि मोनो कंपाइलर ने सिस्टम असेंबली को संदर्भित करने में कुछ गड़बड़ की है। मैं सीधे उनके कोई तिथि नहीं कंसोल उपकरण का नमूना कॉपी करते हैं:

csharp> var list = new int [] {1,2,3}; 
csharp> var b = from x in list 
    > where x > 1 
    > select x; 
csharp> b; 

मैं अपवाद:

{interactive}(1,25): error CS1935: An implementation of `Select' query expressio 
n pattern could not be found. Are you missing `System.Linq' using directive or ` 
System.Core.dll' assembly reference? 

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

धन्यवाद।

+0

क्यों नहीं http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx का उपयोग न करें? – Andrey

+1

CSharpCodeProvider प्रति संकलित एक असेंबली उत्सर्जित करता है और लोड करता है (भले ही आप केवल स्मृति में उपयोग करें)। मैं हजारों मूल्यांकन करूँगा और इस प्रकार हजारों असेंबली निष्पादित एपडोमेन (मेमोरी लीक) में लोड हो जाएंगे। इसके अलावा, CSharpCodeProvider आंतरिक रूप से csc.exe का उपयोग करता है, जो प्रतिबिंब से अधिक प्रोसेसर गहन है। स्वीकार करें। पिछली परियोजना में मैंने CSharpCodeProvider का उपयोग किया, और एक अलग ऐप डोमेन में मूल्यांकन चलाया जिसे असेंबली गिनती के आधार पर पुनर्नवीनीकरण किया गया था, लेकिन यह एक विशाल रखरखाव ओवरहेड और बहुत त्रुटि प्रवण साबित हुआ, इसलिए मैं उस दृष्टिकोण से बचना चाहता हूं। – Jeff

+0

इसके अलावा, मुझे एहसास है कि डिफ़ॉल्ट रूप से एमसीएस प्रति मूल्यांकन एक एकल असेंबली भी करता है, लेकिन चूंकि यह प्रतिबिंब पर निर्भर करता है। आंतरिक रूप से प्रवेश करें, मुझे आशा है कि मैं एपडोमेन द्वारा परिभाषित एक असेंबली को उत्सर्जित करने के लिए उस व्यवहार को बदल सकता हूं। डीफिन डायनामिकएस्प्लोर। – Jeff

उत्तर

2

ठीक है, मुझे लगता है कि मेरे पास कुछ जवाब हैं।

विधानसभा लोड समस्या को हल करने, मैं एक कॉल कर सकते हैं या तो Mono.CSharp.Driver.LoadAssembly अंदर Assembly.LoadWithPartialName, या करने के लिए अपने आवेदन

 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 

     private static bool isResolving; 
     static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
     { 
      if (!isResolving) 
      { 
       isResolving = true; 
       var a = Assembly.LoadWithPartialName(args.Name); 
       isResolving = false; 
       return a; 
      } 
      return null; 
     } 

मोनो ही पुन: उपयोग करने के लिए में निम्नलिखित प्रत्येक मूल्यांकन/संकलन कॉल के लिए गतिशील असेंबली, मुझे बस बदलना था (हालांकि यहां शायद जटिलताएं हैं जो मुझे याद आ रही हैं) .....

Mono.CSharp के अंदर।

/// <summary> 
/// Gets or sets a value indicating whether to auto reset when evaluations are performed and create a new assembly. 
/// </summary> 
/// <value><c>true</c> if [auto reset]; otherwise, <c>false</c>.</value> 
public static bool AutoReset { get; set; } 

फिर ... सुनिश्चित रीसेट Init में कम से कम एक बार कहा जाता है बनाने: मूल्यांकनकर्ता, मैं संपत्ति जोड़ा

static void Init() 
    { 
     Init (new string [0]); 
     Reset(); 
    } 

और अंत में, ParseString में, बस जब तक AutoReset है रीसेट नहीं करते सच ...

 static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input) 
     { 
. 
. 
. 
      if (AutoReset) Reset(); 
+0

तो, मुझे यह वही समस्या है। क्या Mono.CSharp.dll का एक संकलित संस्करण है जिसमें आपके ऊपर वर्णित परिवर्तन हैं? मैं इसे एक एप्लिकेशन में उपयोग करना चाहता हूं लेकिन मुझे यह बहुत अस्थिर लगता है। –

+0

आपके पास क्या समस्या है? क्या आपने ऊपर दिए गए परिवर्तनों को करने का प्रयास किया है? यदि आपको वास्तव में इसकी आवश्यकता है, तो मैं एक डीएल प्रदान कर सकता हूं, लेकिन आप इन बदलावों को स्वयं और डीएलएल को संकलित करने से शायद बेहतर हो सकते हैं। – Jeff

+0

इसके अलावा, मेरे अंत में, इन परिवर्तनों के बाद मुझे वास्तव में किसी भी अन्य समस्या का सामना नहीं हुआ है ... क्या आप? – Jeff

1

मिगुएल के ब्लॉग पेज के मुताबिक आपने लिंक किया है, आपको .NET पर LINQ का उपयोग करने के लिए System.Core का संदर्भ जोड़ना होगा।

csharp> using System.Linq; 
csharp> from x in "Foo" select x; 
+0

आह ... मैं देखता हूं, लेकिन एक संदर्भ जोड़ना पर्याप्त नहीं है क्योंकि यह बिन निर्देशिका में जीएसी असेंबली या फ्रेमवर्क असेंबली की प्रतिलिपि नहीं करता है। – Jeff

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