I have a class as below
public class Details
{
public string CreatedAt {set;get;)
public Order Order { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public CustomerAddress Address { get; set; }
}
public class CustomerAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
}
and I have HTML file with HTML content and few placeholder. I am replacing placeholders as below.
public static string ReplaceStringPlaceHolders(User Details)
{
string MyHTML= File.ReadAllText(@"...Path");
//Replacing one by one
string newstring= MyHTML.
.Replace("{created_at}", Details.CreatedAt)
.Replace("{customer_info.address.line_1}", Details.Customer.Address.Line1)
.Replace("{customer_info.address.line_2}", Details.Customer.Address.Line2)
.Replace("{customer_info.address.city}", Details.Customer.Address.City)
.Replace("{customer_info.address.state}", Details.Customer.Address.State)
.Replace("{customer_info.address.postal_code}", Details.Customer.Address.PostalCode)
.Replace("{customer_info.address.country}", Details.Customer.Address.Country)
return newstring;
}
but I don't like this way as I have put 50 placeholders in my HTML file. Is there a way that we can replace the placeholder when the placeholder name matches to class properties.
I am looking for something like this if possible:
MyHTML.replaceifPlaceHolderMatchesWithClassProperties(Label);
Kindly suggest.
CodePudding user response:
i think this will help you:
string MyHTML = "{PersonId}, {Name}, {Family}, {Age}";
Person p = new Person();
p.PersonId = 0;
p.Name = "hello";
p.Family = "world";
p.Age = 15;
var properties = typeof(Person).GetProperties().ToDictionary(x => x, x => x.GetType().GetProperties());
foreach (var item in properties)
MyHTML = MyHTML.Replace("{" item.Key.Name "}", typeof(Person).GetProperty(item.Key.Name).GetValue(p).ToString());
Console.WriteLine(MyHTML);
output: 0, hello, world, 15
CodePudding user response:
Yes, you can read properties with a help of Reflection and Linq:
using System.Linq;
using System.Reflection;
....
private static string TryReadReflectionValue(object data, string name) {
if (name == null)
return null;
foreach (string item in name.Replace("_", "").Trim('{', '}').Split('.')) {
if (data == null)
return null;
var prop = data
.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.Public)
.Where(p => p.Name.Equals(item, StringComparison.OrdinalIgnoreCase))
.Where(p => p.CanRead)
.Where(p => p.GetIndexParameters().Length <= 0)
.FirstOrDefault();
if (prop == null)
return null;
data = prop.GetValue(prop.GetGetMethod().IsStatic ? null : data);
}
return data?.ToString();
}
And match placeholders with a help of regular expressions:
using System.Text.RegularExpressions;
...
private static string MyReplace(string text, object data) {
if (text == null)
return text;
return Regex.Replace(
text,
@"\{\w._] \}",
match => TryReadReflectionValue(data, match.Value) ?? match.Value);
}
Usage:
public static string ReplaceStringPlaceHolders(User Details) {
string MyHTML= File.ReadAllText(@"...Path");
return MyReplace(text, Details);
}
Here I assumed that
- We always drop
_
in placeholders, e.g{created_at}
corresponds toCreatedAt
property - We ignore case in placeholders:
{created_at} == {Created_At} == {CREATED_at}
etc. - All placeholders are in
{letters,digits,_,.}
format