Existe-t-il un moyen d’exécuter de manière dynamic une chaîne dans .net, similaire à eval () dans JavaScript ou SQL dynamic dans SQL?

Existe-t-il un moyen d’exécuter dynamicment le code contenu dans une chaîne à l’aide de .net 2.0, de la même manière que eval () en javascript ou en utilisant sp_executeSQL dans tsql?

J’ai une valeur de chaîne dans une variable que je souhaite manipuler à un moment donné de mon application – le code serait donc essentiellement une manipulation de chaîne. Je ne sais pas quelles sont les différentes manipulations nécessaires, je voudrais donc qu’elles soient configurables.

Je ne me soucie pas vraiment de la langue dans laquelle le code dynamic est écrit, de ce qui est le plus facile à implémenter et assez simple à écrire.

Par exemple, je pourrais vouloir remplacer des instances de ‘.’ caractère avec ‘-‘, ou supprimer tous les espaces, ou similaire. Si je faisais cela en SQL, j’utiliserais SQL dynamic, mais je veux l’exécuter en code .net, quelque chose comme ceci:

// Get the value to be manipulated ssortingng s = ... // wherever s comes from // Get the manipulation code, eg this might come from a database // setting that can be changed without recompiling the .net code. ssortingng manipulation = Settings.GetSomeValue("ManipulationSetting"); // This is what I want to know how to do: apply some manipulation to the ssortingng. ssortingng result = MagicDynamicEvalClass.Eval(manipulation, s); // Now I would do stuff with the result. 

Je pourrais éventuellement simplement utiliser des expressions regex find / replace. Étant donné que je ne fais que manipuler des chaînes, cela devrait suffire, à condition que je puisse écrire des expressions rationnelles assez intelligentes. par exemple:

 // Get the value to be manipulated ssortingng s = ... // wherever s comes from // Get the code to use to manipulate s, eg this might come from a database // setting that can be changed without recompiling the .net code. ssortingng findRegex = Settings.GetSomeValue("RegexPattern"); ssortingng replaceRegex = Settings.GetSomeValue("RegexReplace"); // This is what I want to know how to do: apply some manipulation to the ssortingng. ssortingng result = Regex.Replace(s, findRegex, replaceRegex); // Now I can do stuff with the result. 

Mais dans certains cas, mon exigence de manipulation peut dépasser ce qui est possible avec regex, ou je peux vouloir appliquer plusieurs étapes, par exemple remplacer “.” avec ‘-‘ et aussi des espaces de bande. Je pourrais peut-être stocker une liste de expressions rationnelles rechercher / remplacer et les parcourir par la suite … mais quiconque a une meilleure suggestion?

UPDATE – exemple d’utilisation de SQL dynamic

Je ne veux pas d’une solution qui demande que je sache à l’avance quelles manipulations sont possibles, et je cherche vraiment quelque chose de simple. par exemple dans sql je ferais quelque chose comme ceci:

 declare @s nvarchar(1000) declare @manipulation nvarchar(1000) declare @result nvarchar(1000) -- ... Get the values from wherever they come from -- Execute the manipulation dynamically EXEC sp_ExecuteSQL @stmt = @manipulation , @params = N'@s nvarchar(1000), @result nvarchar(1000) OUTPUT' , @s = @s, @result = @result OUTPUT 

Ensuite, je pourrais mettre du code SQL arbitraire dans ma manipulation, comme ceci: SET @result = REPLACE (REPLACE (@s, ‘.’, ‘-‘), ”, ”)

Oui, cela nécessiterait que je fasse attention aux valeurs autorisées à figurer dans @manipulation, mais cela me donnerait la flexibilité dont j’ai besoin à l’avenir.

Une approche similaire serait possible en javascript, je suppose, en utilisant eval ().

UPDATE – exemple d’utilisation du contrôle MSScript à partir de .net:

Cela semble être une approche possible, bien que peut-être exagéré pour le cas simple que je veux traiter. Il utilise la bibliothèque Microsoft Script Control pour permettre l’exécution de VBScript arbitraires.

comme les autres déjà mentionnés, il n’est pas vraiment possible de comstackr c # dans une fonction eval (). cette fonctionnalité est prévue pour une dernière version de la clé qui a été démontrée par le PDC.

En tant que solution différente, si votre application est capable de fonctionner en mono, vous pouvez simplement utiliser sa fonction eval qui permet de comstackr dynamicment le code c #, tout comme javascript. en gros, nous faisons déjà ce que .net sera capable de faire dans un an ou deux.

sinon, si vous ne pouvez pas utiliser mono, vous pouvez écrire la partie qui manipule la chaîne dans ironruby, qui a eval (). le rest de votre code ne saura même pas que vous utilisez ruby ​​pour cette classe / assambly.

le lien que vous avez posté dans la mise à jour semble assez compliqué pour un cas d’utilisation aussi simple. en utilisant ironruby, tout ce que vous auriez à faire est d’écrire le MyDynamicEvalClass comme ceci:

 class MyDynamicEvalClass def eval(someSsortingng,transformSsortingng) eval(someSsortingng,transformSsortingng) end end 

et en remplaçant “ManipulationSetting” par du code ruby ​​qui renvoie une nouvelle chaîne

Ce n’est pas trop difficile;) J’ai mis en place un petit exemple. Cela devrait vous aider à décider si vous souhaitez utiliser des scripts dynamics .. ou des expressions rationnelles.

Ce que vous pouvez faire est de créer une interface dans votre assembly, que votre code dynamic implémentera:

 namespace ComstackScriptExample { public interface ISsortingngManipulator { ssortingng processSsortingng(ssortingng aSsortingng); } } 

Puis créez une classe ScriptRunner:

 namespace ComstackScriptExample { public class ScriptRunner { public static ssortingng RunScript(ssortingng scriptCode, ssortingng scriptParameter) { CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider(); //configure parameters ComstackrParameters parameters = new ComstackrParameters(); parameters.GenerateExecutable = false; parameters.GenerateInMemory = true; parameters.IncludeDebugInformation = false; ssortingng reference; // Set reference to current assembly - this reference is a hack for the example.. reference = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); parameters.ReferencedAssemblies.Add(reference+"\\ComstackScriptExample.exe"); //comstack ComstackrResults results = provider.ComstackAssemblyFromSource(parameters, new ssortingng[] { scriptCode }); if (results.Errors.Count == 0) { ISsortingngManipulator comstackdScript=(ISsortingngManipulator)FindInterface(results.ComstackdAssembly, "ISsortingngManipulator"); return comstackdScript.processSsortingng(scriptParameter);//run the script, pass the ssortingng param.. } else { foreach(ComstackrError anError in results.Errors) { MessageBox.Show(anError.ErrorText); } //handle compilation errors here //..use results.errors collection throw new Exception("Compilation error..."); } } private static object FindInterface(Assembly anAssembly, ssortingng interfaceName) { // find our interface type.. foreach (Type aType in anAssembly.GetTypes()) { if (aType.GetInterface(interfaceName, true) != null) return anAssembly.CreateInstance(aType.FullName); } return null; } } 

}

Il ne vous rest plus qu’à créer une chaîne de script avec du code qui implémente votre interface, comme ..

 ssortingng myScriptSsortingng=@"using ComstackScriptExample; public class MySsortingngManipulator : ISsortingngManipulator { public ssortingng processSsortingng(ssortingng aSsortingng) { return aSsortingng+aSsortingng; } }; 

et ensuite .. dans votre code, utilisez ScriptRunner pour traiter votre chaîne avec votre code dynamic:

 ssortingng processedSsortingng = ScriptRunner.RunScript(myScriptSsortingng, "hello"); 

Je sais que vous recherchez C # mais le code que j’ai pour cela est en VB. Vous pouvez le traduire assez facilement à l’aide du convertisseur VB en C # de Developer Fusion. Je l’ai utilisé dans un projet pour permettre aux utilisateurs d’append des calculs complexes à leur application au moment de l’exécution. Il comstack leur code VB dans une bibliothèque en mémoire, puis exécute le code renvoyant la sortie résultante. Il pourrait être réutilisé assez facilement pour ce que vous essayez de faire.

 Imports System.Reflection Imports System.CodeDom.Comstackr Imports System.Text.RegularExpressions Imports System.Math Module Module1 Function Evaluate(ByVal Expression As Ssortingng, ByVal Args() As Object) As Object If Expression.Length > 0 Then 'Replace each parameter in the calculation expression with the correct values Dim MatchStr = "{(\d+)}" Dim oMatches = Regex.Matches(Expression, MatchStr) If oMatches.Count > 0 Then Dim DistinctCount = (From m In oMatches _ Select m.Value).Distinct.Count If DistinctCount = Args.Length Then For i = 0 To Args.Length - 1 Expression = Expression.Replace("{" & i & "}", Args(i)) Next Else Throw New ArgumentException("Invalid number of parameters passed") End If End If Dim FuncName As Ssortingng = "Eval" & Guid.NewGuid.ToSsortingng("N") Dim FuncSsortingng As Ssortingng = "Imports System.Math" & vbCrLf & _ "Namespace EvaluatorLibrary" & vbCrLf & _ " Class Evaluators" & vbCrLf & _ " Public Shared Function " & FuncName & "() As Double" & vbCrLf & _ " " & Expression & vbCrLf & _ " End Function" & vbCrLf & _ " End Class" & vbCrLf & _ "End Namespace" 'Tell the comstackr what language was used Dim CodeProvider As CodeDomProvider = CodeDomProvider.CreateProvider("VB") 'Set up our comstackr options... Dim ComstackrOptions As New ComstackrParameters() With ComstackrOptions .ReferencedAssemblies.Add("System.dll") .GenerateInMemory = True .TreatWarningsAsErrors = True End With 'Comstack the code that is to be evaluated Dim Results As ComstackrResults = _ CodeProvider.ComstackAssemblyFromSource(ComstackrOptions, FuncSsortingng) 'Check there were no errors... If Results.Errors.Count > 0 Then Else 'Run the code and return the value... Dim dynamicType As Type = Results.ComstackdAssembly.GetType("EvaluatorLibrary.Evaluators") Dim methodInfo As MethodInfo = dynamicType.GetMethod(FuncName) Return methodInfo.Invoke(Nothing, Nothing) End If Else Return 0 End If Return 0 End Function End Module 

J’ai configuré mon code dynamic comme ceci:

 Dim Expr As Ssortingng = " If ({0} < 20000) Then" & vbCrLf & _ " Return Max(15, Min(75,0.12*{0}))" & vbCrLf & _ " Else" & vbCrLf & _ " Return Max(75,0.05*{0})" & vbCrLf & _ " End If" 

Et ensuite, configurez des arguments pour l'expression et exécutez:

 Dim Args As New List(Of Ssortingng) While True Dim Val As Ssortingng = Console.ReadLine Args.Clear() If IsNumeric(Val) Then Args.Add(Val) Dim dblOut As Object = Evaluate(Expr, Args.ToArray) Console.WriteLine(dblOut) Else Exit While End If End While 

Je pense qu’il est possible de faire cela avec reflect.emit et codedom, mais ce n’est pas du tout anodin et je le déconseille.

Au lieu de cela, vous pouvez essayer de configurer une chaîne de format, éventuellement en plus de l’expression régulière.

Que diriez-vous de ma solution pour Eval

comment exécuter le chemin de chaîne sur le type dynamic?

Bien que vous puissiez utiliser une énumération pour indiquer l’action que vous souhaitez entreprendre ou utiliser CodeDom pour émettre du code de manière dynamic, vous devez définir une transformation, ce qui signifie que vous avez des entrées et une sortie. .

Déterminer la sortie est facile dans ce cas, vous avez une chaîne. Pour les entrées, il semblerait que vous puissiez avoir un nombre variable d’entrées. Ce serait défini comme un IEnumerable .

Dans cet esprit, vous pouvez définir une interface comme ceci:

 public interface ISsortingngManipulation { ssortingng Manipulate(IEnumerable parameters); } 

Il serait alors facile de définir des implémentations de ce type, puis de placer les noms de type dans votre configuration.

Vous voulez vraiment faire cela au lieu de comstackr dynamicment le code à partir de chaînes. En utilisant des chaînes, vous avez beaucoup de flexibilité, oui, mais vous n’avez pas de temps de compilation, et vous vous exposez à des bogues et à des problèmes de sécurité.

En outre, le temps qu’il faudra pour écrire un morceau de code pour émettre du code basé sur le fragment de chaîne que vous fournissez sera également assez fastidieux, car vous devez construire l’assembly, la classe, la méthode, puis comstackr , puis appelez la méthode que vous avez compilée dynamicment par reflection (à moins que cette dernière ne mette en œuvre une interface, auquel cas, vous pouvez également faire ce que je propose de toute façon).

L’autre jour, je suis tombé sur quelque chose qui existe dans un autre langage .NET: http://reverseblade.blogspot.com/2009/02/dont-wait-for-c-5-use-nemerle.html

J’imagine que vous pourriez écrire votre code de traitement de chaîne dans nemerle, comstackr et référencer à partir de votre application C # ou VB.

Je préférerais toujours un design extensible comme le suggère casperOne. En faisant un script dynamic, vous allez simplement pousser la compilation dans l’application et le déploiement dans n’importe quel processus qui acheminera les chaînes de programmation vers l’application. Mais il semble que vous ayez vos raisons, alors la seule autre chose que je considérerais ici est la sécurité. Idéalement, vous voulez limiter autant que possible l’utilisateur à la manipulation de chaînes, auquel cas List-of-Regex semble être une très bonne option.

Il n’y a pas de méthode intégrée en C # pour appeler eval () au moment de l’exécution.

Cependant, mon programme C # eval permet d’évaluer le code C #. Il permet d’évaluer le code C # au moment de l’exécution et prend en charge de nombreuses instructions C #. En fait, ce code est utilisable dans tout projet .NET, cependant, il est limité à l’utilisation de la syntaxe C #. Consultez mon site Web, http://csharp-eval.com , pour plus de détails.