Search code examples
c#jsonjson.net

Pass a reference of an object's property to a method


I'm trying to learn how to pass some type of an argument that will tell a method which property it should edit.

I'm trying to save an object with two string lists to a json file. So I have an "Add" method that adds a string to one of the lists, and that's where I need a parameter that determines/points/refers to which list I want the method to add to.

I've tried to use Enums but then I'll have to use a lot of if statements in the method and I feel like there should be a better way to do it.

I've tried the ref keyword but then I have to create the object (before calling the "Add" method) and pass it to the method, but I don't want that, I want the method to create an object on it's own and know which list it must edit.

NOTE: the following code has generic names and doesn't use lists and the whole json stuff for the sake of simplicity and clarity

NOTE: the next code is taken from a console app

NOTE: the "ChangeStuff" method's parameter (refProp) isn't right because I don't know what else to put there.

So I want the method to work something like this:

class Stuff
    {
        public string One = "Normal";
        public string Two = "Normal";
    }

class Program
    {
        static void Main(string[] args)
        {
            var StuffObject = new Stuff();
            ChangeStuff(StuffObject.One);
        }

        static void ChangeStuff(refProp)
        {
            Stuff StuffObject = new Stuff();
            StuffObject.refProp = "Changed";
            Console.WriteLine(StuffObject.refProp);
        }
    }

I expect ChangeStuff to make an object and change the property that "refProp" points to and then writes that property's value to the console.


Solution

  • You could make use of Expressions for referring properties in your class in order to change them. For example,

    static void Main(string[] args)
    {
        var stuffObject = new Stuff();
        var result = ChangeStuff(stuffObject,x=>x.Two);
    }
    
    static T ChangeStuff<T>(T target,Expression<Func<T,object>> exp)
    {
         var memberSelectorExpression = exp.Body as MemberExpression;
         if (memberSelectorExpression != null)
         {
            var property = memberSelectorExpression.Member as PropertyInfo;
    
            if (property != null)
            {
              property.SetValue(target, "Changed", null);
            }
          }
          return target;
    }
    

    Please note, you need to make your One and Two in the Class Stuff as Properties.

    class Stuff
    {
            public string One {get;set;} ="Normal";
            public string Two {get;set;} ="Normal";
    }
    

    You could extend it further by passing the "New Value" as parameter.

    static TSource ChangeStuff<TSource,TValue>(TSource target,Expression<Func<TSource,TValue>> exp,TValue newValue)
    {
        var memberSelectorExpression = exp.Body as MemberExpression;
        if (memberSelectorExpression != null)
        {
            var property = memberSelectorExpression.Member as PropertyInfo;
            if (property != null)
            {
                property.SetValue(target, newValue, null);
            }
        }
        return target;
    }
    

    Now you could call the method as

    ChangeStuff(stuffObject,x=>x.Two,"This is new value");