Действительно ли возможно сериализировать блок кода C#?

22
задан Peter Mortensen 15 April 2012 в 21:41
поделиться

7 ответов

ДА!!!

Мы сделали это для очень реального случая производительности. Выполнение этого во времени выполнения или использование DSL не были опцией из-за производительности.

Мы компилируем код в блок и разрываем IL из метода. Мы тогда получаем все метаданные, связанные с этим методом, и сериализируем целую путаницу через XML, сжимаем его и помещаем его в нашу базу данных.

Во время регидратации, мы воссоздаем IL с метаданными с помощью класс DynamicMethod и выполняем его.

Мы делаем это из-за скорости. У нас есть тысячи из небольших блоков кода. К сожалению, скомпилировать блок кода и выполнить его на лету берут по крайней мере 250 мс, который является слишком медленным для нас. Мы проявили этот подход, и он работает ДЕЙСТВИТЕЛЬНО хорошо. Во времени выполнения требуется неизмеримое количество времени, чтобы воссоздать метод и выполнить его.

Только вещь следить... Блоки со знаком и Неподписанные блоки не могут смешать сериализированные данные метода.

18
ответ дан 29 November 2019 в 05:07
поделиться

Вы могли попытаться использовать IronPython в Вашем проекте. Это тривиально , чтобы сделать то, что Вы спрашиваете в Python. Код Python мог назвать Ваши методы C#. Что касается безопасности, Вы могли выполнить код в ограниченной среде некоторого вида (один пример RestrictedPython).

7
ответ дан 29 November 2019 в 05:07
поделиться

Вообще говоря, это походит на действительно плохую идею и большую дыру в системе безопасности.

Вы не хотите, чтобы другой процесс выполнил любой код. Поймите то, что Вам действительно нужен другой процесс, чтобы сделать и создать немного DSL вокруг этого.

4
ответ дан 29 November 2019 в 05:07
поделиться

Вы могли также отправить его, поскольку строка тогда использует CodeDomProvider для компиляции его, тот же результат. У меня есть бит в качестве примера кода таким образом:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;

namespace DynamicCodeApplication
{
    class azCodeCompiler
    {
        private List<string> assemblies;

        public azCodeCompiler()
        {
            assemblies = new List<string>();
            scanAndCacheAssemblies();
        }

        public Assembly BuildAssembly(string code)
        {

            CodeDomProvider prov = CodeDomProvider.CreateProvider("CSharp");
            string[] references = new string[] { };   // Intentionally empty, using csc.rsp
            CompilerParameters cp = new CompilerParameters(references)
                                        {
                                            GenerateExecutable = false,
                                            GenerateInMemory = true
                                        };
            string path = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
            cp.CompilerOptions = "@" + path + @"\csc.rsp";
            CompilerResults cr = prov.CompileAssemblyFromSource(cp, code);

            foreach (CompilerError err in cr.Errors)
            {
                Console.WriteLine(err.ToString());
            }
            return cr.CompiledAssembly;
        }

        public object ExecuteCode(string code,
                                  string namespacename, string classname,
                                  string functionname, bool isstatic, params object[] args)
        {
            object returnval = null;
            Assembly asm = BuildAssembly(code);
            object instance = null;
            Type type = null;
            if (isstatic)
            {
                type = asm.GetType(namespacename + "." + classname);
            }
            else
            {
                instance = asm.CreateInstance(namespacename + "." + classname);
                type = instance.GetType();
            }
            MethodInfo method = type.GetMethod(functionname);
            returnval = method.Invoke(instance, args);
            return returnval;
        }

        private void scanAndCacheAssemblies()
        {

            /*
            foreach (string str in Directory.GetFiles(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727"))
            {
                if (str.Contains(".dll"))
                {
                    foreach (string st in str.Split(new char[] { '\\' }))
                    {
                        if (st.Contains(".dll"))
                        {
                            assemblies.Add(st);
                        }
                    }
                }
            }
             * */

            assemblies.Add("Accessibility.dll");
            assemblies.Add("AspNetMMCExt.dll");
            assemblies.Add("cscompmgd.dll");
            assemblies.Add("CustomMarshalers.dll");
            assemblies.Add("IEExecRemote.dll");
            assemblies.Add("IEHost.dll");
            assemblies.Add("IIEHost.dll");
            assemblies.Add("Microsoft.Build.Conversion.dll");
            assemblies.Add("Microsoft.Build.Engine.dll");
            assemblies.Add("Microsoft.Build.Framework.dll");
            assemblies.Add("Microsoft.Build.Tasks.dll");
            assemblies.Add("Microsoft.Build.Utilities.dll");
            assemblies.Add("Microsoft.Build.VisualJSharp.dll");
            assemblies.Add("Microsoft.CompactFramework.Build.Tasks.dll");
            assemblies.Add("Microsoft.JScript.dll");
            assemblies.Add("Microsoft.VisualBasic.Compatibility.Data.dll");
            assemblies.Add("Microsoft.VisualBasic.Compatibility.dll");
            assemblies.Add("Microsoft.VisualBasic.dll");
            assemblies.Add("Microsoft.VisualBasic.Vsa.dll");
            assemblies.Add("Microsoft.Vsa.dll");
            assemblies.Add("Microsoft.Vsa.Vb.CodeDOMProcessor.dll");
            assemblies.Add("Microsoft_VsaVb.dll");
            assemblies.Add("mscorlib.dll");
            assemblies.Add("sysglobl.dll");
            assemblies.Add("System.configuration.dll");
            assemblies.Add("System.Configuration.Install.dll");
            assemblies.Add("System.Data.dll");
            assemblies.Add("System.Data.OracleClient.dll");
            assemblies.Add("System.Data.SqlXml.dll");
            assemblies.Add("System.Deployment.dll");
            assemblies.Add("System.Design.dll");
            assemblies.Add("System.DirectoryServices.dll");
            assemblies.Add("System.DirectoryServices.Protocols.dll");
            assemblies.Add("System.dll");
            assemblies.Add("System.Drawing.Design.dll");
            assemblies.Add("System.Drawing.dll");
            assemblies.Add("System.EnterpriseServices.dll");
            assemblies.Add("System.Management.dll");
            assemblies.Add("System.Messaging.dll");
            assemblies.Add("System.Runtime.Remoting.dll");
            assemblies.Add("System.Runtime.Serialization.Formatters.Soap.dll");
            assemblies.Add("System.Security.dll");
            assemblies.Add("System.ServiceProcess.dll");
            assemblies.Add("System.Transactions.dll");
            assemblies.Add("System.Web.dll");
            assemblies.Add("System.Web.Mobile.dll");
            assemblies.Add("System.Web.RegularExpressions.dll");
            assemblies.Add("System.Web.Services.dll");
            assemblies.Add("System.Windows.Forms.dll");
            assemblies.Add("System.XML.dll");
            assemblies.Add("vjscor.dll");
            assemblies.Add("vjsjbc.dll");
            assemblies.Add("vjslib.dll");
            assemblies.Add("vjslibcw.dll");
            assemblies.Add("vjssupuilib.dll");
            assemblies.Add("vjsvwaux.dll");
            assemblies.Add("vjswfc.dll");
            assemblies.Add("VJSWfcBrowserStubLib.dll");
            assemblies.Add("vjswfccw.dll");
            assemblies.Add("vjswfchtml.dll");
            assemblies.Add("Accessibility.dll");
            assemblies.Add("AspNetMMCExt.dll");
            assemblies.Add("cscompmgd.dll");
            assemblies.Add("CustomMarshalers.dll");
            assemblies.Add("IEExecRemote.dll");
            assemblies.Add("IEHost.dll");
            assemblies.Add("IIEHost.dll");
            assemblies.Add("Microsoft.Build.Conversion.dll");
            assemblies.Add("Microsoft.Build.Engine.dll");
            assemblies.Add("Microsoft.Build.Framework.dll");
            assemblies.Add("Microsoft.Build.Tasks.dll");
            assemblies.Add("Microsoft.Build.Utilities.dll");
            assemblies.Add("Microsoft.Build.VisualJSharp.dll");
            assemblies.Add("Microsoft.CompactFramework.Build.Tasks.dll");
            assemblies.Add("Microsoft.JScript.dll");
            assemblies.Add("Microsoft.VisualBasic.Compatibility.Data.dll");
            assemblies.Add("Microsoft.VisualBasic.Compatibility.dll");
            assemblies.Add("Microsoft.VisualBasic.dll");
            assemblies.Add("Microsoft.VisualBasic.Vsa.dll");
            assemblies.Add("Microsoft.Vsa.dll");
            assemblies.Add("Microsoft.Vsa.Vb.CodeDOMProcessor.dll");
            assemblies.Add("Microsoft_VsaVb.dll");
            assemblies.Add("mscorlib.dll");
            assemblies.Add("sysglobl.dll");
            assemblies.Add("System.configuration.dll");
            assemblies.Add("System.Configuration.Install.dll");
            assemblies.Add("System.Data.dll");
            assemblies.Add("System.Data.OracleClient.dll");
            assemblies.Add("System.Data.SqlXml.dll");
            assemblies.Add("System.Deployment.dll");
            assemblies.Add("System.Design.dll");
            assemblies.Add("System.DirectoryServices.dll");
            assemblies.Add("System.DirectoryServices.Protocols.dll");
            assemblies.Add("System.dll");
            assemblies.Add("System.Drawing.Design.dll");
            assemblies.Add("System.Drawing.dll");
            assemblies.Add("System.EnterpriseServices.dll");
            assemblies.Add("System.Management.dll");
            assemblies.Add("System.Messaging.dll");
            assemblies.Add("System.Runtime.Remoting.dll");
            assemblies.Add("System.Runtime.Serialization.Formatters.Soap.dll");
            assemblies.Add("System.Security.dll");
            assemblies.Add("System.ServiceProcess.dll");
            assemblies.Add("System.Transactions.dll");
            assemblies.Add("System.Web.dll");
            assemblies.Add("System.Web.Mobile.dll");
            assemblies.Add("System.Web.RegularExpressions.dll");
            assemblies.Add("System.Web.Services.dll");
            assemblies.Add("System.Windows.Forms.dll");
            assemblies.Add("System.XML.dll");
            assemblies.Add("vjscor.dll");
            assemblies.Add("vjsjbc.dll");
            assemblies.Add("vjslib.dll");
            assemblies.Add("vjslibcw.dll");
            assemblies.Add("vjssupuilib.dll");
            assemblies.Add("vjsvwaux.dll");
            assemblies.Add("vjswfc.dll");
            assemblies.Add("VJSWfcBrowserStubLib.dll");
            assemblies.Add("vjswfccw.dll");
            assemblies.Add("vjswfchtml.dll");


            return;
        }
    }
}
3
ответ дан 29 November 2019 в 05:07
поделиться

Скомпилируйте его в отдельный блок, отправьте блок, имейте другую загрузку процесса он.

Вы могли бы хотеть рассмотреть последствия безопасности.

Обновление: другая идея состояла бы в том, чтобы генерировать дерево выражений и пользоваться этой библиотекой для сериализации ее:

http://www.codeplex.com/metalinq/

1
ответ дан 29 November 2019 в 05:07
поделиться

Другая опция использует ДОЛЛАР и вынуждает код выполняться...

0
ответ дан 29 November 2019 в 05:07
поделиться

Это - интересная задача, но необходимо, вероятно, описать, почему Вы хотите сделать это, так как существует много разных подходов в зависимости от Вашей цели. Как humpohl указывает, существуют также некоторые довольно серьезные проблемы безопасности.

"Сериализированный код" мог просто быть исходным кодом или скомпилированным блоком, в зависимости от Ваших требований. Вы, вероятно, не должны использовать отдельный формат сериализации кода.

, Если Вы хотите сгенерировать код динамично и передать это, Вы могли бы сгенерировать код с помощью CodeDOM и скомпилировать его. Однако Вы, скорее всего, не должны генерировать абсолютно произвольный код.

1
ответ дан 29 November 2019 в 05:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: