C# Reflection: replace all occurrence of property with value in text
If you want to generate the string you can use Linq
to enumerate the properties:
MyClass test = new MyClass {
FirstName = "John",
LastName = "Smith",
};
String result = "My Name is " + String.Join(" ", test
.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(property => property.CanRead) // Not necessary
.Select(property => property.GetValue(test)));
// My Name is John Smith
Console.Write(result);
In case you want to substitute within the string (kind of formatting), regular expressions can well be your choice in order to parse the string:
String original = "My Name is @MyClass.FirstName @MyClass.LastName";
String pattern = "@[A-Za-z0-9\\.]+";
String result = Regex.Replace(original, pattern, (MatchEvaluator) ((match) =>
test
.GetType()
.GetProperty(match.Value.Substring(match.Value.LastIndexOf('.') + 1))
.GetValue(test)
.ToString() // providing that null can't be returned
));
// My Name is John Smith
Console.Write(result);
Note, that in order to get instance (i. e. not static
) property value you have to provide the instance (test
in the code above):
.GetValue(test)
so @MyClass part in the string is useless, since we can get type directly from instance:
test.GetType()
Edit: in case that some properties can return null
as value
String result = Regex.Replace(original, pattern, (MatchEvaluator) ((match) => {
Object v = test
.GetType()
.GetProperty(match.Value.Substring(match.Value.LastIndexOf('.') + 1))
.GetValue(test);
return v == null ? "NULL" : v.ToString();
}));
First of all, I'd advice against using reflection when other options such as string.Format
is possible. Reflection can make your code less readable and harder to maintain. Either way, you could do it like this:
public void Main()
{
string str = "My Name is @MyClass.FirstName @MyClass.LastName";
var me = new MyClass { FirstName = "foo", LastName = "bar" };
ReflectionReplace(str, me);
}
public string ReflectionReplace<T>(string template, T obj)
{
foreach (var property in typeof(T).GetProperties())
{
var stringToReplace = "@" + typeof(T).Name + "." + property.Name;
var value = property.GetValue(obj);
if (value == null) value = "";
template = template.Replace(stringToReplace, value.ToString());
}
return template;
}
This should require no additional changes if you want to add a new property to your class and update your template string to include the new values. It should also handle any properties on any class.
Using Reflection you can achieve it as shown below
MyClass obj = new MyClass() { FirstName = "Praveen", LaseName = "Paulose" };
string str = "My Name is @MyClass.FirstName @MyClass.LastName";
string firstName = (string)obj.GetType().GetProperty("FirstName").GetValue(obj, null);
string lastName = (string)obj.GetType().GetProperty("LaseName").GetValue(obj, null);
str = str.Replace("@MyClass.FirstName", firstName);
str = str.Replace("@MyClass.LastName", lastName);
Console.WriteLine(str);
You are first finding the relevant Property using GetProperty
and then its value using GetValue
UPDATE
Based on further clarification requested in the comment
You could use a regex to identify all placeholders in your string. i.e. @MyClass.Property. Once you have found them you can use Type.GetType to get the Type information and then use the code shown above to get the properties. However you will need the namespace to instantiate the types.