Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Reflection: replace all occurrence of property with value in text

I have a class like

public class MyClass {

  public string FirstName {get; set;}
  public string LastName {get; set;}

}

The case is, I have a string text like,

string str = "My Name is @MyClass.FirstName @MyClass.LastName";

what I want is to replace @MyClass.FirstName & @MyClass.LastName with values using reflection which are assigned to objects FirstName and LastName in class.

Any help please?

like image 826
Aqdas Avatar asked Nov 12 '15 14:11

Aqdas


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


3 Answers

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(); 
 }));
like image 58
Dmitry Bychenko Avatar answered Oct 14 '22 00:10

Dmitry Bychenko


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.

like image 29
Kvam Avatar answered Oct 13 '22 23:10

Kvam


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.

like image 41
Praveen Paulose Avatar answered Oct 14 '22 01:10

Praveen Paulose