I'm thinking of this a lot like MVVM one way binding in AngularJS. I have an object (a "model") with a few properties and a few methods - something like
{
"firstName": "John",
"lastName": "Doe",
"random": () => Random.Next(),
"formatDate": (fmt, value) => new DateTime(value).ToString(fmt)
}
I'd like to define a format string which can access values from the model or call methods from it and get back the formatted string. In AngularJS I would use an expression like this
Hello {firstName} {lastName}. Today is {formatDate('d', new Date())}.
Is there a way to do something similar in C# (.NET 5)? I'm looking to do this on string
s.
Here are the ideas I've come up with and the problems with them
- WPF / XAML. This is a ton of overhead I don't care about. I only want to format
string
s. - Roslyn. This requires me to write the format expressions as valid C#. It's also a lot of work.
- Formattable strings / ICustomFormatter. This doesn't have support for passing a dynamic model or for method calls.
EDIT
Here's a sample of what the calling code might look like
var formatString = person.Tenant.WelcomeMessageFormat;
var model = new
{
FirstName = person.FirstName,
LastName = person.LastName,
Random = () => Random.Next(),
FormatDate = (fmt, value) => new DateTime(value).ToString(fmt)
};
var message = ParseFormatString(formatString, model);
SendMessage(message);
// .....
public string ParseFormatString(string format, object model)
{
// what goes here?
}
CodePudding user response:
Are you looking for a templating library? That seems to be what you are describing. Here is an sample from the web http://r3c.github.io/cottle/
CodePudding user response:
This is pretty much a duplicate of Dynamic string interpolation but here's the dotnet core answer.
Install nuget package System.Linq.Dynamic.Core
using System;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using DynLinq = System.Linq.Dynamic;
namespace aaq
{
class Model
{
private Random _random = new Random();
public string FirstName { get; set; }
public string LastName { get; set; }
public int Random => _random.Next();
public string FormatDate(string format, DateTime value) => value.ToString(format);
};
class Program
{
static void Main(string[] args)
{
var m = new Model()
{
FirstName = "firstly",
LastName = "lastly",
};
Console.WriteLine(ReplaceMacro("a", m));
Console.WriteLine(ReplaceMacro("hello {FirstName} {LastName}", m));
Console.WriteLine(ReplaceMacro("date: {FormatDate(String.Empty, DateTime.Now)}", m));
}
static string ReplaceMacro(string value, Model m)
{
return Regex.Replace(value, @"{(?<exp>[^}] )}", match => {
var p = Expression.Parameter(typeof(Model), "Model");
var e = DynLinq.Core.DynamicExpressionParser.ParseLambda(new[] { p }, null, match.Groups["exp"].Value);
return (e.Compile().DynamicInvoke(m) ?? "").ToString();
});
}
}
}
Console output:
a
hello firstly lastly
date: 9/20/2022 12:05:23 PM