Pozdravljeni!
Imam sledeč problem. Rad bi naredi, da mi program bral c# funkcije (npr. Math.abs(x), kjer je x seznam parametrov, ki jih dobim iz programa) iz xml datoteke. Tukaj se pa pojavi problem prevajanja. Slišal sem, da se da to rešiti tako, da napišeš script (npr. c#), ki se izvrši ob zagonu programa in v bistvu izvede prevajanje. Morda kdo ve o tem kaj več oz. pozna kakšno drugo rešitev.
Hvala
Matjaž
Avtor: o-MA-n-tjaz, objavljeno na portalu SloDug.si (Arhiv)
damjank - četrtek, 19. oktober 2006
Sem imel pred časom podoben problem - dinamično prevajanje c# kode iz datoteke XML (naknadno dodajanje funkcionalnosti brez novega grajenja z VS.NET) in nalaganje zbira v trenutno aplikacijsko domeno.Sistem ob zagonu preveri XML datoteko, če je njeno stanje od prejšnjega zagona spremenjeno, se izvede dinamično prevajanje kode.Npr. datoteka XML s programsko kodo za dinamično prevajanje:<?xml version="1.0" encoding="utf-8" ?><runtimeCode> <outputAssembly>bin/RuntimeCode.dll</outputAssembly> <includeDebugInformation>true</includeDebugInformation> <referencedAssemblies> <add name="system.dll" virtualPath="false" /> <add name="system.data.dll" virtualPath="false" /> <add name="system.web.dll" virtualPath="false" /> <add name="bin/BusinessEntities.dll" virtualPath="true" /> <add name="bin/CommonInterfaces.dll" virtualPath="true" /> <add name="bin/Exceptions.dll" virtualPath="true" /> <add name="bin/ExceptionHandling.dll" virtualPath="true" /> <add name="bin/Microsoft.ApplicationBlocks.ExceptionManagement.dll" virtualPath="true" /> </referencedAssemblies> <code> <![CDATA[using System;using System.Text;using System.Data;using System.Reflection;using System.Configuration;using System.Collections;using System.Collections.Generic;using System.Web;using System.Web.Caching;namespace IIS.WebCore { /// <summary> /// Razred za branje podatkov. /// </summary> public class DataBridge { private static Cache cache = HttpContext.Current != null ? HttpContext.Current.Cache : null; public DataBridge() { } /// <summary> /// Vrne šifrant vrednost (zalogo) za podano PI polje. /// </summary> /// <param name="_sProfile">Profil.</param> /// <param name="_sPIIndex">PI index.</param> /// <param name="_sFieldName">Ime PI polja.</param> /// <param name="_sFilterFields">Morebitna filter PI polja loÄŤena z ';'.</param> /// <param name="_sFilterValues">Vrednosti morebitnih PI polj loÄŤene z ';'.</param> /// <returns>Seznam.</returns> public IEnumerable GetPIValues(string _sPIIndex, string _sFieldName, string _sFilterFields, string _sFilterValues) { object[] oArgs = new object[] { Settings.AppServerProfile, _sPIIndex, _sFieldName, _sFilterFields, _sFilterValues }; IEnumerable data = null; // ali za te argumente Ĺľe obstaja cache vrednost StringBuilder sb = new StringBuilder(); for (int ii = 0; ii < oArgs.Length; ii++) { sb.Append(oArgs[ii]); } string sHash = Hash.GetHash(sb.ToString(), HashType.MD5); if (cache != null && cache[sHash] != null) { data = cache[sHash] as IEnumerable; } else { data = CommonHelper.InvokeRemoteMethod("GetPIValues", oArgs) as IEnumerable; if (cache != null) { cache.Insert(sHash, data, null, DateTime.Now.AddHours(24d), Cache.NoSlidingExpiration); } } return data; } ]]> </code></runtimeCode>....Izsek kode, ki prevede zadevo v zbir (assemlby) - uporaba CodeDOM prevajalnika:using System;using System.IO;using System.Web;using System.Data;using System.Configuration;using System.Collections;using System.Collections.Specialized;using System.Reflection;using System.CodeDom.Compiler;public class DnyCompiler { private volatile static object syncRoot = new Object(); /// <summary> /// Prevede programsko kodo. /// </summary> public static void Compile() { lock (syncRoot) { CompilerParameters cparams = null; ... try { ... // branje & členitev XML datoteke ... string sCodeToCompile = ....; cparams = new CompilerParameters(); cparams.TempFiles = new TempFileCollection(AppDomain.CurrentDomain.SetupInformation.CachePath, false); cparams.OutputAssembly = ...; cparams.GenerateExecutable = false; cparams.GenerateInMemory = false; cparams.IncludeDebugInformation = bDebug; // ref. zbiri for (int ii = 0; ii < dtRefAssemblies.Rows.Count; ii++) { cparams.ReferencedAssemblies.Add(....); } // referenca na trenutni zbir, ki se izvaja cparams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName); // prevajanje v zbir CodeDomProvider provider = new CSharpCodeProvider(); CompilerResults = provider.CompileAssemblyFromSource(cparams, sCodeToCompile); if (cresults.Errors.HasErrors) { StringBuilder error = new StringBuilder(); foreach (CompilerError err in cresults.Errors) { error.AppendFormat("{0}\n", err.ErrorText); } throw new ApplicationException(string.Format("Napaka pri prevajanju: {0}.", error.ToString())); } .... } }}..Prevedena koda (zbir), oz. nova funkcionalnost, je na voljo brez ponovnega grajenja (build) rešitve - primer uporabe klica metode v aspx datoteki:...<asp:objectdatasource runat="server" id="DS_Values" selectmethod="GetPIValues" typename="IIS.WebCore.DataBridge, RuntimeCode"> <selectparameters> <asp:parameter name="_sPIIndex" type="String" defaultvalue="PI_Core" /> <asp:parameter name="_sFieldName" type="String" defaultvalue="Classification" /> <asp:parameter name="_sFilterFields" type="String" defaultvalue="" /> <asp:parameter name="_sFilterValues" type="String" defaultvalue="" /> </selectparameters></asp:objectdatasource>..Na ta način je precej olajšano dodajanje nove funkcionalnosti. Seveda pa obstajajo še drugi načini (VSA scripting,..).Lp, Damjan
damjank - četrtek, 19. oktober 2006
Sem imel pred časom podoben problem - dinamično prevajanje c# kode iz datoteke XML (naknadno dodajanje funkcionalnosti brez novega grajenja z VS.NET) in nalaganje zbira v trenutno aplikacijsko domeno.Sistem ob zagonu preveri XML datoteko, če je njeno stanje od prejšnjega zagona spremenjeno, se izvede dinamično prevajanje kode.Npr. datoteka XML s programsko kodo za dinamično prevajanje:<?xml version="1.0" encoding="utf-8" ?><runtimeCode> <outputAssembly>bin/RuntimeCode.dll</outputAssembly> <includeDebugInformation>true</includeDebugInformation> <referencedAssemblies> <add name="system.dll" virtualPath="false" /> <add name="system.data.dll" virtualPath="false" /> <add name="system.web.dll" virtualPath="false" /> <add name="bin/BusinessEntities.dll" virtualPath="true" /> <add name="bin/CommonInterfaces.dll" virtualPath="true" /> <add name="bin/Exceptions.dll" virtualPath="true" /> <add name="bin/ExceptionHandling.dll" virtualPath="true" /> <add name="bin/Microsoft.ApplicationBlocks.ExceptionManagement.dll" virtualPath="true" /> </referencedAssemblies> <code> <![CDATA[using System;using System.Text;using System.Data;using System.Reflection;using System.Configuration;using System.Collections;using System.Collections.Generic;using System.Web;using System.Web.Caching;namespace IIS.WebCore { /// <summary> /// Razred za branje podatkov. /// </summary> public class DataBridge { private static Cache cache = HttpContext.Current != null ? HttpContext.Current.Cache : null; public DataBridge() { } /// <summary> /// Vrne šifrant vrednost (zalogo) za podano PI polje. /// </summary> /// <param name="_sProfile">Profil.</param> /// <param name="_sPIIndex">PI index.</param> /// <param name="_sFieldName">Ime PI polja.</param> /// <param name="_sFilterFields">Morebitna filter PI polja loÄŤena z ';'.</param> /// <param name="_sFilterValues">Vrednosti morebitnih PI polj loÄŤene z ';'.</param> /// <returns>Seznam.</returns> public IEnumerable GetPIValues(string _sPIIndex, string _sFieldName, string _sFilterFields, string _sFilterValues) { object[] oArgs = new object[] { Settings.AppServerProfile, _sPIIndex, _sFieldName, _sFilterFields, _sFilterValues }; IEnumerable data = null; // ali za te argumente Ĺľe obstaja cache vrednost StringBuilder sb = new StringBuilder(); for (int ii = 0; ii < oArgs.Length; ii++) { sb.Append(oArgs[ii]); } string sHash = Hash.GetHash(sb.ToString(), HashType.MD5); if (cache != null && cache[sHash] != null) { data = cache[sHash] as IEnumerable; } else { data = CommonHelper.InvokeRemoteMethod("GetPIValues", oArgs) as IEnumerable; if (cache != null) { cache.Insert(sHash, data, null, DateTime.Now.AddHours(24d), Cache.NoSlidingExpiration); } } return data; } ]]> </code></runtimeCode>....Izsek kode, ki prevede zadevo v zbir (assemlby) - uporaba CodeDOM prevajalnika:using System;using System.IO;using System.Web;using System.Data;using System.Configuration;using System.Collections;using System.Collections.Specialized;using System.Reflection;using System.CodeDom.Compiler;public class DnyCompiler { private volatile static object syncRoot = new Object(); /// <summary> /// Prevede programsko kodo. /// </summary> public static void Compile() { lock (syncRoot) { CompilerParameters cparams = null; ... try { ... // branje & členitev XML datoteke ... string sCodeToCompile = ....; cparams = new CompilerParameters(); cparams.TempFiles = new TempFileCollection(AppDomain.CurrentDomain.SetupInformation.CachePath, false); cparams.OutputAssembly = ...; cparams.GenerateExecutable = false; cparams.GenerateInMemory = false; cparams.IncludeDebugInformation = bDebug; // ref. zbiri for (int ii = 0; ii < dtRefAssemblies.Rows.Count; ii++) { cparams.ReferencedAssemblies.Add(....); } // referenca na trenutni zbir, ki se izvaja cparams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName); // prevajanje v zbir CodeDomProvider provider = new CSharpCodeProvider(); CompilerResults = provider.CompileAssemblyFromSource(cparams, sCodeToCompile); if (cresults.Errors.HasErrors) { StringBuilder error = new StringBuilder(); foreach (CompilerError err in cresults.Errors) { error.AppendFormat("{0}\n", err.ErrorText); } throw new ApplicationException(string.Format("Napaka pri prevajanju: {0}.", error.ToString())); } .... } }}..Prevedena koda (zbir), oz. nova funkcionalnost, je na voljo brez ponovnega grajenja (build) rešitve - primer uporabe klica metode v aspx datoteki:...<asp:objectdatasource runat="server" id="DS_Values" selectmethod="GetPIValues" typename="IIS.WebCore.DataBridge, RuntimeCode"> <selectparameters> <asp:parameter name="_sPIIndex" type="String" defaultvalue="PI_Core" /> <asp:parameter name="_sFieldName" type="String" defaultvalue="Classification" /> <asp:parameter name="_sFilterFields" type="String" defaultvalue="" /> <asp:parameter name="_sFilterValues" type="String" defaultvalue="" /> </selectparameters></asp:objectdatasource>..Na ta način je precej olajšano dodajanje nove funkcionalnosti. Seveda pa obstajajo še drugi načini (VSA scripting,..).Lp, Damjan
MihaM - sobota, 16. september 2006
Seveda, najlažje je prevest v zbir (assembly).Mogoče si poglej tole povezavo: http://www.codeproject.com/csharp/cs-script_for_cp.asp