C#在新对象实例中为特定类型的所有字段动态分配特定的默认值吗?

时间:2018-03-29 20:56:35

标签: c# .net serialization

我有一个包含多个字符串字段的类。每当实例化此类的对象时,我希望这些字段自动分配相同的特定默认值(类似“未定义”)。原因是:

  • 如果我必须在使用实际数据填充所有字段之前序列化对象,我希望这些字段显示为此默认值,而不是null或string.Empty。

  • 随着项目的进展,可以在此类中添加/删除字符串字段。我希望每次发生时都不必触摸构造函数。

除了在类构造函数中逐个显式地为每个字符串字段分配默认值之外,还有什么方法可以做到这一点吗?

9 个答案:

答案 0 :(得分:2)

在C#6.0及更高版本中,您可以使用Auto-Property Initializer

https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-6#auto-property-initializers

基本上:

public string Property { get; set; } = "UNDEFINED";

答案 1 :(得分:1)

你必须使用反射。像这样的东西

Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties();

foreach (PropertyInfo property in properties)
{
    if (property.PropertyType == typeof(string)) property.setValue(obj, "UNDEFINED");
}

答案 2 :(得分:1)

首先:我不知道如何做到你想要的最佳做法。

如果你想在你的代码中显示这样的东西:

public string Property { get; set; } = "UNDEFINED";

您应该考虑创建自定义片段,只需编写完全相同的片段。例如https://msdn.microsoft.com/en-us/library/ms165394.aspx

如果您不想这样,可以使用反射来查找构造函数中的所有字段(例如字符串)并进行设置。

C# Reflection - Get field values from a simple class

FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public | 
                                          BindingFlags.NonPublic | 
                                          BindingFlags.Instance);

Setting a property by reflection with a string value

Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);

答案 3 :(得分:0)

那么,为什么不使用像

这样的扩展方法
<textarea placeholder="multi line place holder text in many lines" 
style="height: 50px;"></textarea>

对于类型

public static class MyClass
{
  public static string GetDefault(this str, string defaultVal)
 {
   return string.IsNullOrEmpty(str) ? defaultVal : str;
 }
}

你可以打电话

public class SomeClass
{
  public string str = string.Empty;
}

答案 4 :(得分:0)

您可以直接将值初始化为字段而不是构造函数。

private string myStringVariable = "UNDEFINED";

也许您应该重新考虑程序的结构,但是如果它允许将许多字段初始化为未定义。

答案 5 :(得分:0)

也许我误解了这个,但为什么不在你的构造函数中逐字逐句地解释你在问题中描述的内容呢?

    public class Weee
    {
        public string name { get; set; }
        public int order { get; set; }
        public string whatever { get; set; }

        public Weee()
        {
            foreach(var p in typeof(Weee).GetProperties().Where(a => a.PropertyType == typeof(string)))
            {
                p.SetValue(this, "wut");
            }
        }
    }

答案 6 :(得分:0)

您可以创建属性初始值设定项并让基类使用它。然后,您的类可以从基类继承并自动初始化其属性:

public class PropertyInitializer
{
    public void Initialize<T>(object obj, T value)
    {
        PropertyInfo[] properties = obj.GetType().GetProperties();
        foreach (PropertyInfo property in properties)
        {
            if (property.PropertyType == typeof(T))
            {
                property.SetValue(obj, value);
            }
        }
    }
}

public class InitializedBase
{
    protected InitializedBase()
    {
        var initializer = new PropertyInitializer();
        //Initialize all strings 
        initializer.Initialize<string>(this, "Juan");
        //Initialize all integers
        initializer.Initialize<int>(this, 31);
    }
}

//Sample class to illustrate
public class AutoInitializedClass : InitializedBase
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override string ToString()
    {
        return string.Format("My name is {0} and I am {1} years old", Name, Age);
    }
}

样本用法:

AutoInitializedClass sample = new AutoInitializedClass();
Console.WriteLine(sample);

控制台输出:

  

我的名字是胡安,我今年31岁

请注意,基类使用PropertyInitializer类来初始化字段。这是一个简化的例子。您可以根据自己的需要进行扩展(它可能不适合所有类型的开箱即用)。

我个人不建议这样做。出于某种原因,它被称为构造函数,但您提出了一个问题,我提供了答案。

答案 7 :(得分:0)

这是一个简单的类,您可以从中继承它完全符合您的要求:

使用示例:

public class MyClass : DefaultedObject<string>
{
    public string MyStringField;
    protected override string Default => "UNDEFINED";
}

var myClass = new MyClass();
// myClass.MyStringField == "UNDEFINED"

实现:

public abstract class DefaultedObject<T>
{
    protected DefaultedObject()
    {
        T defaultValue = Default;
        FieldInfo[] fields = GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        foreach(FieldInfo field in fields) {
            if(field.FieldType == typeof(T)) {
                field.SetValue(this, defaultValue);
            }
        }
    }

    protected abstract T Default { get; }
}

答案 8 :(得分:0)

我感谢所有对这个问题的反馈。最终结果起作用了。首先,对于我想要接收自动默认值的类中的任何字符串属性,我建立了属性:

public string attribute1 {get; set;}
public string attribute2 {get; set;}

等等。然后,在类构造函数中,我包含了以下循环,它循环遍历string类型的每个属性:

foreach(PropertyInfo property in GetType().GetProperties())
{
    if (property.PropertyType == typeof(string))
        property.SetValue(this, "UNDEFINED"));
}

这为我带来了理想的结果。