0

I have the following class example here:

public class Foo
{
    public int Id { get; set; }

    public string Bar { get; set; }
    public string FooBar { get; set; }
    public string Fizz { get; set; }
    public string Buzz { get; set; }

    public static Foo Create(int id, string property, string value)
    {
        return new Foo
        {
            Id = id,

        };
    }
}

Now, however, i want to set for example only Bar to a value in the Create method of the class if the propertyname is Bar . So i took a look at C# setting/getting the class properties by string name but i can't get this to work in the create method. Same goes for Setting a property by reflection with a string value so i'm kinda lost here.

As a small bit of clarification. I can get the above methods to work in the create, however not in the return which is where it needs to work.

The solution below seems to work for us for now, however, i think it could be optimized.

public class Foo
{
    public int Id { get; set; }

    public string Bar { get; set; }
    public string FooBar { get; set; }
    public string Fizz { get; set; }
    public string Buzz { get; set; }

    public static Foo Create(int id, string property, string value)
    {
        return new Foo
        {
            WebshopCustomerId = webshopCustomerId,
            Bar = (typeof(Foo)).GetProperty(property).Name == "Bar" ? value : null,
            FooBar = (typeof(Foo)).GetProperty(property).Name == "FooBar" ? value : null,
            Fizz = (typeof(Foo)).GetProperty(property).Name == "Fizz" ? value : null,
            Buzz = (typeof(Foo)).GetProperty(property).Name == "Buzz" ? value : null,
        };
    }
}
9
  • If you cant get it to work show us what you did.. we might be able to help you fix it
    – BugFinder
    Commented Oct 8, 2018 at 8:17
  • I'd advise against solving this using reflection. Instead put those properties into a Dictionary which will free you from having to recompile every time you add a new property.
    – Filburt
    Commented Oct 8, 2018 at 8:18
  • @Filburt The properties are pretty static, and when they change we need to change them in other places as well. So that would not be an problem. Also, the reason we place this in a class is for serialization later.
    – Vincentw
    Commented Oct 8, 2018 at 8:20
  • 1
    Why do you need that? Which problem do you try to solve?
    – Yurii N.
    Commented Oct 8, 2018 at 8:26
  • It still looks suspiciously like a anti-pattern to seemingly have a class depend on the property being set in it's constructor. I guess your actual class doesn't only have 4 properties but considerably more. Otherwise you could simply have 4 overloading constructors.
    – Filburt
    Commented Oct 8, 2018 at 8:27

3 Answers 3

2

You can avoid reflection and keep everything simpler using a dictionary of Actions:

public class Foo
{
    public int Id { get; set; }

    public string Bar { get; set; }
    public string FooBar { get; set; }
    public string Fizz { get; set; }
    public string Buzz { get; set; }

    private static Dictionary<string, Action<Foo, string>> _propertySetters =
        new Dictionary<string, Action<Foo, string>>()
        {
            { "Bar", (foo, value) => foo.Bar = value },
            { "FooBar", (foo, value) => foo.FooBar = value },
            { "Fizz", (foo, value) => foo.Fizz = value },
            { "Buzz", (foo, value) => foo.Buzz = value },
        };

    public static Foo CreateWithProperty(int id, string property, string value)
    {
        if (String.IsNullOrEmpty(property) || !_propertySetters.ContainsKey(property))
            throw new ArgumentException("property");

        var instance = new Foo { Id = id };

        var setter = _propertySetters[property];

        setter(instance, value);

        return instance;
    }
}

With this approach, you can even change the property names, while keeping the configuration values the same. Depending upon the situation, it could be a huge advantage.

Having said this, I feel that your requirement could probably be better answered with more context information and a slightly different design. YMMV.

1
public static Foo Create(int id, string property, string value)
{
    Foo ret = new Foo
    {
        Id = id
    };
    foreach (FieldInfo element in typeof(Foo).GetFields())
        if (element.Name == property)
            element.SetValue(ret, value);
    foreach (PropertyInfo element in typeof(Foo).GetProperties())
        if (element.Name == property)
            element.SetValue(ret, value);
    return ret;
}

Something looking like this should work for you, you could also use

ret.GetType().GetProperty(property).SetValue(ret, value);
ret.GetType().GetField(property).SetValue(ret, value);

But you'll have to handle errors.

0

It will work for you, but you still need to check if property is a valid property.

       public static Foo Create(int id, string property, string value)
       {
           Foo foo = new Foo() { Id = id };

           PropertyInfo propertyInfo = foo.GetType().GetProperty(property);
           propertyInfo.SetValue(foo, Convert.ChangeType(value, propertyInfo.PropertyType), null);
           return foo;
       }
3
  • While this would work in the create, it would not work in the return function which is where it needs to work. In the create i was able to implement the 2 examples which i linked in my original post. However i am unable to figure out how to set only Bar in the return.
    – Vincentw
    Commented Oct 8, 2018 at 8:23
  • So if I understand well, you'd like to do everything inside your return new block?
    – koviroli
    Commented Oct 8, 2018 at 8:30
  • Yes, i have added an new example i am currently working on to see if that works for me.
    – Vincentw
    Commented Oct 8, 2018 at 8:31

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.