سؤال

كنت أتساءل عما إذا كان من الممكن تجميع ، وتشغيل التعليمات البرمجية المخزنة ، دون إنشاء EXE أو أي نوع من الملفات الأخرى ، قم بتشغيل الملف بشكل أساسي من الذاكرة.

في الأساس ، سيكون للتطبيق الرئيسي بعض التعليمات البرمجية المخزنة (رمز من المحتمل أن يتم تغييره) ، وسيحتاج إلى تجميع الكود وتنفيذه. دون إنشاء أي ملفات.

إن إنشاء الملفات ، وتشغيل البرنامج ، ثم حذف الملفات ليس خيارًا. سوف تحتاج إلى تشغيل الرمز المترجم من الذاكرة.

أمثلة رمز ، أو مؤشرات ، أو إلى حد كبير أي شيء مرحب به :)

هل كانت مفيدة؟

المحلول

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() 
        {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");

    var obj = Activator.CreateInstance(type);

    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

هذا يجمع فئة بسيطة من سلسلة التعليمات البرمجية المصدر المتضمنة ، ثم يقوم بتثبيت الفصل ويحتجز بشكل عكسي وظيفة عليها.

نصائح أخرى

إليك مثال على كيفية الاستخدام System.Linq.Expressions للإضافة إلى إجابة تيم. من الواضح أنه ليس أجمل رمز ولكن وجوده في هذا النموذج اللطيف الذي يشبه الأشجار يجعل التنمية سهلة للغاية.

private  Expression<IsWordChar> CreateIsWordCharExpression()
{
    var e = Expression.Parameter(typeof(int), "e");
    var c = Expression.Variable(typeof(char), "c");
    var returnLabel = Expression.Label(Expression.Label(typeof(bool)), _falseConstant);
    var lambda = Expression.Lambda<IsWordChar>(
        Expression.Block(
            new[] { c },
            Expression.IfThen(
                Expression.OrElse(
                    Expression.Equal(e, Expression.Constant(-1)),
                    Expression.Equal(e, _inputLengthVar)
                ),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            Expression.Assign(c, Expression.MakeIndex(_str, _stringCharsPropertyInfo, new[] { e })),
            Expression.IfThenElse(
                Expression.OrElse(
                    Expression.OrElse(
                        Expression.OrElse(
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('a')),
                                Expression.LessThanOrEqual(c, Expression.Constant('z'))
                            ),
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('A')),
                                Expression.LessThanOrEqual(c, Expression.Constant('Z'))
                            )
                        ),
                        Expression.AndAlso(
                            Expression.GreaterThanOrEqual(c, Expression.Constant('0')),
                            Expression.LessThanOrEqual(c, Expression.Constant('1'))
                        )
                    ),
                    Expression.Equal(c, Expression.Constant('_'))
                ),
                Expression.Return(returnLabel.Target, _trueConstant),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            returnLabel
        ),
        "IsWordChar",
        new[] { e }
    );
    return lambda;
}

انه ممكن. إنه سهل أو صعب ، اعتمادًا على مقدار الرمز الذي تريد كتابته.

  • تجميع تعبيرات الخط الواحد: System.Linq.Expressions (واضحة ولكن محدودة)
  • تجميع البرامج بأكملها: System.Reflection.Emit (يصعب تصحيحه ، ولكن ليس مستحيلًا)

يحرر: لاحظ أنه قبل .NET 4.0 ، System.Linq.Expressions يقتصر على ما يمكنك وضعه على سطر واحد من C#: هذا هو ، لا ، في حين ، مهمة متغيرة وما إلى ذلك.

نعم، يمكنك أن تفعل هذا. إنه بطيء جدًا ، لكن يمكنك بالتأكيد القيام بذلك. انظر إلى الترميز أو (new CSharpCodeProvider().CreateCompiler()) في الشباك.

تفحص System.CodeDom. سوف تفعل بالضبط ما تبحث عنه.

في Mono يمكنك استخدام csharp.evaluator. إنه يعمل حقًا في الذاكرة v. بعض الحلول الأخرى المذكورة والتي تكتب مرة أخرى في ملف أسفل الغطاء.

ألقِ نظرة أيضًا على تضمين لغة برمجة مثل Python و Ruby و Lua وما إلى ذلك .. كل تلك الدعم المنفذة للتنفيذ من الذاكرة دون كتابة أي شيء على القرص.

من الصعب ، إن لم يكن من المستحيل تجميع وتنفيذ C# دون إنشاء ملف ، لأن ... حسنًا ، هذا هو ما يحول اللغة إلى ملف قابل للتنفيذ. ما تبحث عنه هو نوع من وظائف البرمجة النصية. ما وصفته في سؤالك هو الفرق بين تفسير اللغة و تجميع وانتاج لغة. نرى ويكيبيديا: لغة البرمجة النصية.

اعتمادًا على ما ستستخدمه هذه الميزة ، يمكنك الاستفادة من لغة البرمجة النصية مثل Python أو Ruby أو Lua. هذا مثال: كيف يمكنني تشغيل نص Python من C#؟

هذا من شأنه أن يجعل التطبيق الخاص بك يعتمد على python.exe (أو أي شيء قابل للتنفيذ تحتاج إلى تشغيل لغة البرمجة النصية التي تختارها). إذا كنت ترغب في تجنب ذلك ، فقد لا يكون من الصعب جدًا إنشاء لغة البرمجة النصية الخاصة بك التي يقوم بها تطبيقك في وقت التشغيل ، اعتمادًا على ما عليك فعله باستخدام البرنامج النصي الذي تم حقنه.

تحرير: تلك الفقرة الأولى هي القمامة. آسف. نرى http://msdn.microsoft.com/en-us/library/8ffc3x75٪28v=vs.110٪29.aspx

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top