【问题标题】:How to use a configuration file to generate and initialize objects at runtime?如何使用配置文件在运行时生成和初始化对象?
【发布时间】:2010-11-17 12:46:09
【问题描述】:

我目前正在做一个项目,我需要在运行时根据配置文件创建对象。

项目示例

这是我正在进行的项目的简化示例。

创建的每个对象都必须实现一个特定的接口,为了示例目的,我们将其称为IObjectInterface

public interface IObjectInterface
{
    void DoSomething();
}

假设我有几个实现这个接口的类,每个类都有一个特定的实现,以及与特定类型相关的多个其他属性:

public class SimpleObject : IObjectInterface
{
    public void DoSomething()
    {
        Console.WriteLine("SimpleObject did something");
    }
}

public class ComplexObject : IObjectInterface
{
    public string ObjectName { get; set; }

    public void DoSomething()
    {
        Console.WriteLine("The ComplexObject named {0} did something", this.ObjectName);
    }
}

public class VeryComplexObject : IObjectInterface
{
    public string ObjectName { get; set; }
    public bool CanDoSomething { get; set; }

    public void DoSomething()
    {
        if (this.CanDoSomething)
        {
            Console.WriteLine("The ComplexObject named {0} did something", this.ObjectName);
        }
        else
        {
            Console.WriteLine("The ComplexObject named {0} tried to do something, but was not allowed to", this.ObjectName);
        }
    }
}

我需要能够使用 ObjectBuilder 类创建与特定 Id 对应的 IObjectInterface 对象:

public class ObjectBuilder
{
    IObjectInterface BuildObject(string objectId)
    {
        // Build object here based on provided Id
    }
}

我正在寻找的是一种在配置文件中指定应该创建的IObjectInterface 的正确实现以及与特定类型关联的参数值的方法。 理想的配置文件应该是这样的:

<objects>
 <object id="Simple">
  <objectInterface type="SimpleObject" />
 </object>
 <object id="Complex">
  <objectInterface type="ComplexObject">
   <ObjectName value="MyObject" />
  </objectInterface>
 </object>
</objects>

我认为我应该能够管理对象实例化部分,但我真的不明白如何使用干净的代码管理实例的初始化。

  • 您对我如何实现这样的配置文件有一些指导吗?
  • 如何轻松创建所需对象的最终实例并使用配置文件中提供的参数对其进行初始化?
  • 是否有任何框架可以帮助我解决我的问题?

【问题讨论】:

  • 也许您只是在寻找serialization
  • @Vlad : 是的,序列化是我的第一个想法,但我对我的用户在编辑配置文件时必须编写“可反序列化”的 xml 感到不舒服

标签: c# configuration


【解决方案1】:

对我来说听起来像是国际奥委会。 StructureMapNInjectMicrosoft Extensibility Framework

【讨论】:

    【解决方案2】:

    您应该能够使用assemblyInstance.GetType(string) 来解析类型(您可能需要使用命名空间作为前缀)- 之后您有两个选择:

    1 使用 Activator.CreateInstance(resolvedType) 实例化和反射属性 - 大概是硬编码一些 PropertyType 方法来解析 stringint

    但这听起来像工作

    2 更改配置文件的格式,使 inner xml 块与 XmlSerializer 兼容 - 然后您可以抓取内部 xml 并运行它

    var ser = new XmlSerializer(resolvedType);
    var obj = (IObjectInterface) ser.Deserialize(...);
    

    (如果您已经有 XmlReader,则使用子树 (ReadSubTree) 阅读器;如果您将 xml 作为字符串,则使用 XmlReader.Create(new StringReader(xml))

    例如xml(想到XmlSerializer)也许:

     <object id="Complex" type="ComplexObject">
      <ComplexObject>
        <ObjectName>MyObject</ObjectName>
      </ComplexObject>
     </object>
    

    【讨论】:

      【解决方案3】:

      您可能希望使用反射来创建配置中提供的类型的实例。

      【讨论】:

        【解决方案4】:

        我在 Java 中做了一些非常相似的事情,我详细解释了我采用的基于反射的方法。我不懂 C#,但显然它类似于 Java,所以我以 Java 为中心的解释可能对你有用。

        您可以在Config4* 提供的“Config4* 实用使用指南”手册的第三部分(“Config4JMS 案例研究”)中找到解释。但是,在阅读之前,我建议您阅读“Config4* 入门指南”的第 2 章和第 3 章,以大致了解配置文件语法和编程 API。这样做会更容易阅读案例研究。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-03
          • 2017-01-28
          • 2013-06-27
          相关资源
          最近更新 更多