【问题标题】:Efficient way of initializing a generic class' fields and/or properties初始化泛型类的字段和/或属性的有效方法
【发布时间】:2011-09-19 10:22:08
【问题描述】:

我正在编写一个 ConfigParser 类,它从如下结构的配置文件中读取:

[Section]
option1 = foo
option2 = 12
option3 = ;
...

读取的信息实际上存储在 Dictionary 中。我想要实现的是:

struct ConfigStruct
{
    public string option1;
    public int option2;
    public char option3 { get; set; }
    // Any other _public_ fields or properties
}

ConfigParser Cp = new ConfigParser("path/to/config/file"); // Loads content
ConfigStruct Cs = Cp.CreateInstance<ConfigStruct>("Section");

Console.WriteLine(Cs.option1); // foo
Console.WriteLine(Cs.option2.ToString()); // 12
Console.WriteLine(Cs.option3.ToString()); // ;

结构体(或类,没关系)ConfigStruct 是特定于应用程序的,ConfigParser 类应该对此一无所知。基本上,我想解析来自特定选项的值,并将其存储到具有相同名称的字段/属性中。应根据字段/属性类型进行解析。

我已经为它开发了一个存根方法:

public T CreateInstance<T>(string Section) where T : new()
{
    // Gets options dictionary from loaded data
    Dictionary<string, string> Options = this.Data[Section];

    T Result = new T();

    Type StructType = Result.GetType();

    foreach (var Field in StructType.GetFields())
    {
        if (!Options.ContainsKey(Field.Name))
            continue;

        Object Value;

        if (Field.FieldType == typeof(bool))
            Value = Boolean.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(int))
            Value = Int32.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(double))
            Value = Double.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(string))
            Value = Options[Field.Name];

        else if (Field.FieldType == typeof(char))
            Value = Options[Field.Name][0];

        // Add any ifs if needed

        else { /* Handle unsupported types */ }

        Field.SetValue(Result, Value);
    }

    foreach (var Property in StructType.GetProperties())
    {
         // Do the same thing with public properties
    }

    return Result;
}
  1. 您认为这是解决问题的正确方法吗?或者我应该将初始化结构的责任转移到应用程序逻辑而不是 ConfigParser 类?我知道它更有效,但是使用反射我只编写了一次这个方法,并且适用于每个结构。
  2. 是否应该使用反射来调用 Parse() 以便避免所有这些 if?或者您更愿意逐个类型地进行这些转换,以防止出现意外行为?

感谢您的宝贵时间。

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    假设您没有使用 app.config/web.config 或其他内置配置文件的特定原因。

    1. 我认为这取决于应用程序的其余部分正在做什么,但我个人会这样做。它允许您干净地获取返回类型,并且您不需要在堆栈中传递额外的 stuct。

    2. 反射是一个很棒的工具,但有一些开销,所以如果类型列表是有限的,那么手动指定它们会更有效,或者只反映未知类型。此外,我会将您的 if 块更改为 switch 语句,如果 IL 编译器可以完全优化条件块,您将获得效率。

    【讨论】:

    • Type 类中使用switch 是不可能的,如果我提供Type.Name 作为switch 参数进行类型检查,这是一种好的编程习惯吗?
    • @silverhx 您应该对示例中列出的类型使用 Type.GetTypeCode。
    【解决方案2】:

    我认为有一个更简单的解决方案。您可以使用自定义部分处理程序来存储您的设置,自定义部分处理程序在此处进行了很好的描述:http://devlicio.us/blogs/derik_whittaker/archive/2006/11/13/app-config-and-custom-configuration-sections.aspx)。

    【讨论】:

    • 我想避免使用 XML,因为配置文件应该在我的应用程序中手动编辑,而 XML 会使这更加冗长。这就是我不使用 app.config 的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多