动态字符串插值

时间:2016-10-05 12:36:54

标签: c# string-interpolation

任何人都可以帮我吗?

必需输出:“管理员的待办事项

$(document).ready(function(){
 $(document).on('click', '#tweet', function(){
 $("#posticon").trigger("submit");
 });
});

12 个答案:

答案 0 :(得分:23)

两个建议:

<强>的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

使用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();
    });
}

在我看来,Linq.Expression更强大,所以如果你信任输入字符串,你可以做更多有趣的事情,即:

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

答案 1 :(得分:7)

您不能以这种方式使用字符串插值。但您仍然可以使用预先C#6方式使用string.Format

static void Main(string[] args)
{
    Console.WriteLine(ReplaceMacro("{0} job for admin", new Job { Id = 1, Name = "Todo", Description = "Nothing" }));
    Console.ReadLine();
}

static string ReplaceMacro(string value, Job job)
{
    return string.Format(value, job.Name);
}

答案 2 :(得分:1)

您需要命名字符串格式替换。多年前见Phil Haack的帖子:http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx/

答案 3 :(得分:0)

来自@ThePerplexedOne的答案更好,但如果你真的需要避免字符串插值,那么

static string ReplaceMacro(string value, Job job)
{
    return value?.Replace("{job.Name}", job.Name); //Output should be "Todo job for admin"
}

答案 4 :(得分:0)

您应该将功能更改为:

static string ReplaceMacro(Job obj, Func<dynamic, string> function)
{
    return function(obj);
}

并称之为:

Console.WriteLine(
    ReplaceMacro(
        new Job { Id = 1, Name = "Todo", Description = "Nothing" },
        x => $"{x.Name} job for admin"));

答案 5 :(得分:0)

此通用解决方案扩展了@Dan提供的答案
它可以用于任何类型的对象。

安装System.Linq.Dynamic

     Install-Package System.Linq.Dynamic -Version 1.0.7 

    string ReplaceMacro(string value, object @object)
    {
        return Regex.Replace(value, @"{(.+?)}", 
        match => {
            var p = Expression.Parameter(@object.GetType(), @object.GetType().Name);                
            var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, match.Groups[1].Value);
            return (e.Compile().DynamicInvoke(@object) ?? "").ToString();
        });
    }

查看working demo以了解客户类型

答案 6 :(得分:0)

不完全是,但仅用了tweek,我创建了仅支持字段/属性的通用插值。

public static string Interpolate(this string template, params Expression<Func<object, string>>[] values)
        {
            string result = template;
            values.ToList().ForEach(x =>
            {
                MemberExpression member = x.Body as MemberExpression;
                string oldValue = $"{{{member.Member.Name}}}";
                string newValue = x.Compile().Invoke(null).ToString();
                result = result.Replace(oldValue, newValue);
            }

                );
            return result;
        }

测试用例

 string jobStr = "{Name} job for admin";
        var d = new { Id = 1, Name = "Todo", Description = "Nothing" };
        var result = jobStr.Interpolate(x => d.Name);

另一个

            string sourceString = "I wanted abc as {abc} and {dateTime} and {now}";
        var abc = "abcIsABC";
        var dateTime = DateTime.Now.Ticks.ToString();
        var now = DateTime.Now.ToString();
        string result = sourceString.Interpolate(x => abc, x => dateTime, x => now);

答案 7 :(得分:0)

将字符串包装在函数中...

var f = x => $"Hi {x}";

f("Mum!");

//... Hi Mum!

答案 8 :(得分:0)

您可以使用RazorEngine

using RazorEngine;

class Program 
{
    static void Main(string[] args)
    {
        Console.WriteLine(ReplaceMacro("@Model.Name job for admin", new Job { Id = 1, Name = "Todo", Description="Nothing" }));
        Console.ReadLine();
    }

    static string ReplaceMacro(string value, Job job)
    {
        return Engine.Razor.RunCompile(value, "key", typeof(Job), job);
    }
}

它甚至支持匿名类型和方法调用:

string template = "Hello @Model.Name. Today is @Model.Date.ToString(\"MM/dd/yyyy\")";
var model = new { Name = "Matt", Date = DateTime.Now };

string result = Engine.Razor.RunCompile(template, "key", null, model);

答案 9 :(得分:0)

如果您确实需要此功能,则可以使用Roslyn进行操作,创建字符串–类实现,例如

var stringToInterpolate = "$@\"{{job.Name}} job for admin\"";
var sourceCode = $@"
using System;
class RuntimeInterpolation(Job job) 
{{
    public static string Interpolate() =>
        {stringToInterpolate};
}}";

然后进行组装

var assembly = CompileSourceRoslyn(sourceCode);
var type = assembly.GetType("RuntimeInterpolation");
var instance = Activator.CreateInstance(type);
var result = (string) type.InvokeMember("Interpolate",
BindingFlags.Default | BindingFlags.InvokeMethod, null, instance, new object[] {new Job { Id = 1, Name = "Todo", Description="Nothing" }});
Console.WriteLine(result);

您将在运行时获得此代码,并获得结果(还需要将作业类的链接附加到该程序集)

using System;
class RuntimeInterpolation(Job job) 
{
    public static string Interpolate() =>
        $@"{job.Name} job for admin";
}

您可以在Roslyn - compiling simple class: "The type or namespace name 'string' could not be found..."

处了解有关如何实现CompileSourceRoslyn的信息。

答案 10 :(得分:0)

晚会晚一点!这是我写的-

using System.Reflection;
using System.Text.RegularExpressions;

public static class AmitFormat
{
    //Regex to match keywords of the format {variable}
    private static readonly Regex TextTemplateRegEx = new Regex(@"{(?<prop>\w+)}", RegexOptions.Compiled);

    /// <summary>
    /// Replaces all the items in the template string with format "{variable}" using the value from the data
    /// </summary>
    /// <param name="templateString">string template</param>
    /// <param name="model">The data to fill into the template</param>
    /// <returns></returns>
    public static string FormatTemplate(this string templateString, object model)
    {
        if (model == null)
        {
            return templateString;
        }

        PropertyInfo[] properties = model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

        if (!properties.Any())
        {
            return templateString;
        }

        return TextTemplateRegEx.Replace(
            templateString,
            match =>
            {
                PropertyInfo property = properties.FirstOrDefault(propertyInfo =>
                    propertyInfo.Name.Equals(match.Groups["prop"].Value, StringComparison.OrdinalIgnoreCase));

                if (property == null)
                {
                    return string.Empty;
                }

                object value = property.GetValue(model, null);

                return value == null ? string.Empty : value.ToString();
            });
    }
}

示例-

string format = "{foo} is a {bar} is a {baz} is a {qux:#.#} is a really big {fizzle}";
var data = new { foo = 123, bar = true, baz = "this is a test", qux = 123.45, fizzle = DateTime.UtcNow };

与Phil Haack给出的其他实现相比,这是上面示例的结果-

AmitFormat    took 0.03732 ms
Hanselformat  took 0.09482 ms
OskarFormat   took 0.1294 ms
JamesFormat   took 0.07936 ms
HenriFormat   took 0.05024 ms
HaackFormat   took 0.05914 ms

答案 11 :(得分:-1)

我真的不明白你的ReplaceMacro方法......

但这是它应该如何运作的:

class Program
{
    static void Main(string[] args)
    {
        var job = new Job { Id = 1, Name = "Todo", Description = "Nothing" };
        Console.WriteLine($"{job.Name} job for admin");
        Console.ReadLine();
    }
}

但是如果你真的想要它的动态感觉,你的ReplaceMacro方法应该只取一个参数,这就是工作:

static string ReplaceMacro(Job job)
{
    return $"{job.Name} job for admin.";
}

并使用它:

var job = new Job { Id = 1, Name = "Todo", Description = "Nothing" };
Console.WriteLine(ReplaceMacro(job));

或者那种效果。