2

I'd love some ideas about how I should implement a key part of a project I am working on. Essentially it is data mapping, where I copy field x and put it into field y. However, there needs to be some ability to dynamically change (using string manipulation) that value during the transition.

What I would like is a textbox where a user could enter script allowing them to modify that value using a scripting language, ideally VBScript. That would then allow them to do simple manipulations such this example, which would take a substring:

Mid({input_value}, 2, 4)

Where

{input_value} 

Would be replaced by the actual value at runtime.

So, for example, if the input from "field x" was "This is a test" and they used the above example of start = 2 and length = 4, the value saved into "field y" would be "his "

I know how I could run VBScript from C# as a scipt, that's not a problem. However, Is it possible to run and evaluate srcipts such as above at runtime and record the output back into a C# variable?

Otherwise, does anyone have any suggestions about how I could approach this?

Many thanks

2 Answers 2

1

You might want to look at a DLR-based language like IronPython or IronRuby. Both allow embedding and Michael Foord has a tutorial on how to embed these in an application.

If you use the standard DLR interfaces I believe you can embed any language including DLRBasic and the ASP Classic Compiler. Ben Hall has an article on IronRuby embedding in a production application for Red Gate.

I think you need to review the SetVariable() and GetVariable() methods shown below for an example of setting and return data from scripts:

public string evaluate(string x, string code)
{
    scope.SetVariable("x", x);
    scope.SetVariable("button", this.button);

    try
    {
        ScriptSource source = engine.CreateScriptSourceFromString(code,
            SourceCodeKind.Statements);

        source.Execute(scope);
    }
    catch (Exception ex)
    {
        return "Error executing code: " + ex.ToString();
    }

    if (!scope.VariableExists("x"))
    {
        return "x was deleted";
    }
    string result = scope.GetVariable<object>("x").ToString();
    return result;
}

This example was taken from http://www.voidspace.org.uk/ironpython/dlr_hosting.shtml.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the post, I am looking at these options now.
However I do have one question - It may be possible to run the script dynamically, but is it possible to get a result returned from IronRuby/IronPython back into a C# variable?
It should be. I think you should look into the C# 'dynamic' keyword on .NET 4.0. There should be a solution to this on earlier versions of .NET but I need to look that up.
Thank you for your response, I'll mark the question as answered
0

Here is a working example using runtime compilation of expressions. I borrowed the concept and most of the code from here.

static void Main(string[] args)
{
    string input = "This is a test";
    string method = "Mid(x, 2, 4)";  // 'x' represents the input value
    string output = Convert(method, input);
    Console.WriteLine("Result: " + output);
    Console.ReadLine();
}

// Convert input using given vbscript logic and return as output string
static string Convert(string vbscript, string input)
{
    var func = GetFunction(vbscript);
    return func(input);
}

// Create a function from a string of vbscript that can be applied
static Func<string, string> GetFunction(string vbscript)
{
    // generate simple code snippet to evaluate expression
    VBCodeProvider prov = new VBCodeProvider();
    CompilerResults results = prov.CompileAssemblyFromSource(
        new CompilerParameters(new[] { "System.Core.dll" }),
        @"
Imports System
Imports System.Linq.Expressions
Imports Microsoft.VisualBasic

Class MyConverter

Public Shared Function Convert() As Expression(Of Func(Of String, String))
    return Function(x) " + vbscript + @"
End Function

End Class
"
        );

    // make sure no errors occurred in the conversion process
    if (results.Errors.Count == 0)
    {
        // retrieve the newly prepared function by executing the code
        var expr = (Expression<Func<string, string>>)
            results.CompiledAssembly.GetType("MyConverter")
                .GetMethod("Convert").Invoke(null, null);
        Func<string, string> func = expr.Compile();

        // create a compiled function ready to apply and return
        return func;
    }
    else
    {
        return null;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.