【问题标题】:C# setting class properties by string name in createC#在create中通过字符串名称设置类属性
【发布时间】:2019-03-12 20:57:03
【问题描述】:

我这里有以下类示例:

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,

        };
    }
}

但是,现在,如果属性名称为 Bar,我只想将 Bar 设置为类的 Create 方法中的值。所以我看了一下C# setting/getting the class properties by string name,但我无法让它在 create 方法中工作。 Setting a property by reflection with a string value 也是如此,所以我有点迷路了。

作为一点澄清。我可以让上述方法在 create 中起作用,但在 return 中不起作用,这是它需要起作用的地方。

下面的解决方案目前似乎对我们有用,但是,我认为它可以进行优化。

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

【问题讨论】:

  • 如果你不能让它工作,请告诉我们你做了什么......我们也许可以帮助你解决它
  • 我建议不要使用反射来解决这个问题。而是将这些属性放入字典中,这样您就不必每次添加新属性时都重新编译。
  • @Filburt 属性是相当静态的,当它们发生变化时,我们也需要在其他地方进行更改。所以这不会是一个问题。另外,我们将它放在一个类中的原因是为了以后序列化。
  • 你为什么需要它?你想解决哪个问题?
  • 它看起来仍然像一个反模式,似乎有一个类依赖于在它的构造函数中设置的属性。我猜你的实际课程不仅有 4 个属性,而且还有更多。否则你可以简单地拥有 4 个重载构造函数。

标签: c# reflection


【解决方案1】:

您可以使用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;
    }
}

使用这种方法,您甚至可以更改属性名称,同时保持配置值不变。根据具体情况,这可能是一个巨大的优势。

话虽如此,我感觉您的要求可能会通过更多的上下文信息和稍微不同的设计得到更好的回答。 YMMV。

【讨论】:

    【解决方案2】:
    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;
    }
    

    看起来像这样的东西应该适合你,你也可以使用

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

    但是你必须处理错误。

    【讨论】:

      【解决方案3】:

      它会为您工作,但您仍需要检查 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;
             }
      

      【讨论】:

      • 虽然这可以在创建中工作,但在需要工作的返回函数中不起作用。在创建中,我能够实现我在​​原始帖子中链接的 2 个示例。但是我无法弄清楚如何在返回中仅设置 Bar。
      • 所以如果我理解得很好,你愿意在你的 return new 块内做所有事情吗?
      • 是的,我添加了一个我目前正在研究的新示例,看看它是否适合我。
      猜你喜欢
      • 2012-05-04
      • 2012-03-21
      • 1970-01-01
      • 2017-04-24
      • 2013-02-10
      • 2012-08-11
      • 1970-01-01
      • 2013-03-11
      相关资源
      最近更新 更多