How to Expand a String That Contains C# Literal Expressions at Runtime

Can I expand a string that contains C# literal expressions at runtime

Similar to Mikael answer but using the CSharpCodeProvider:

    public static string ParseString(string txt)
{
var provider = new Microsoft.CSharp.CSharpCodeProvider();
var prms = new System.CodeDom.Compiler.CompilerParameters();
prms.GenerateExecutable = false;
prms.GenerateInMemory = true;
var results = provider.CompileAssemblyFromSource(prms, @"
namespace tmp
{
public class tmpClass
{
public static string GetValue()
{
return " + "\"" + txt + "\"" + @";
}
}
}");
System.Reflection.Assembly ass = results.CompiledAssembly;
var method = ass.GetType("tmp.tmpClass").GetMethod("GetValue");
return method.Invoke(null, null) as string;
}

You might be better off using a dictionary of wildcards and just replacing them in the string.

Insert variable values in the middle of a string

You can use string.Format:

string template = "Hi We have these flights for you: {0}. Which one do you want";
string data = "A, B, C, D";
string message = string.Format(template, data);

You should load template from your resource file and data is your runtime values.

Be careful if you're translating to multiple languages, though: in some cases, you'll need different tokens (the {0}) in different languages.

Dynamic string interpolation

Two suggestions:

DataBinder.Eval

string ReplaceMacro(string value, Job job)
{
return Regex.Replace(value, @"{(?<exp>[^}]+)}", match => {
return (System.Web.UI.DataBinder.Eval(new { Job = job }, match.Groups["exp"].Value) ?? "").ToString();
});
}

Linq.Expression

Use the Dynamic Query class provided in the MSDN LINQSamples:

string ReplaceMacro(string value, Job job)
{
return Regex.Replace(value, @"{(?<exp>[^}]+)}", match => {
var p = Expression.Parameter(typeof(Job), "job");
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(job) ?? "").ToString();
});
}

In my opinion, the Linq.Expression is more powerful, so if you trust the input string, you can do more interesting things, i.e.:

value = "{job.Name.ToUpper()} job for admin"
return = "TODO job for admin"

How to force a runtime constant to be a compile time constant?

You can't, in general. Anything which involves a method call is not going to be a compile-time constant, as far as the compiler is concerned.

What you can do is express a double literal using scientific notation though:

public const double AvogadrosNumber = 6.022e-22;

So in this specific case you can write it with no loss of readability.

In other settings, so long as the type is one of the primitive types or decimal, you can just write out the constant as a literal, and use a comment to explain how you got it. For example:

// Math.Sqrt(Math.PI)
public const double SquareRootOfPi = 1.7724538509055159;

Note that even though method calls can't be used in constant expressions, other operators can. For example:

// This is fine
public const double PiSquared = Math.PI * Math.PI;

// This is invalid
public const double PiSquared = Math.Pow(Math.PI, 2);

See section 7.19 of the C# 5 specification for more details about what is allowed within a constant expression.

Resolving a parameter name at runtime

One way:

static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}

This code also requires a supporting function:

static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}

Basically the code works by defining a new Anonymous Type with a single Property consisting of the parameter who's name you want. GetName() then uses reflection to extract the name of that Property.

There are more details here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html

ReferenceEquals working wrong with strings

The first example has a compile time constant "fg" that is referenced by two variables. Since this is a compile time constant, the two variables reference the one object. The references are equal.

Read into the topic of string interning for more on this behavior. As a starter, consider:

For example, if you assign the same literal string to several variables, the runtime retrieves the same reference to the literal string from the intern pool and assigns it to each variable.

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

In the second example, only one is a compile time constant, the other is a result of some operations. a and d do not reference the same object, so you get the false result from ReferenceEquals.



Related Topics



Leave a reply



Submit