简体   繁体   中英

C# setting class properties by string name in create

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,
        };
    }
}

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

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.

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;
       }
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM