【问题标题】:Extensible .NET Configuration可扩展的 .NET 配置
【发布时间】:2013-01-29 00:10:25
【问题描述】:

我想分发一个带有ConfigurationSection 的DLL,如下所示:

public class StandardConfiguration : ConfigurationSection
{
    public static StandardConfiguration GetInstance()
    {
        return (StandardConfiguration)ConfigurationManager.GetSection("customConfigSection");
    }

    [ConfigurationProperty("childConfig")]
    public StandardChildConfig ChildConfig
    {
        get { return (StandardChildConfig)this["childConfig"]; }
        set { this["childConfig"] = value; }
    }
}

public class StandardChildConfig : ConfigurationElement
{
    [ConfigurationProperty("p1")]
    public string P1
    {
        get { return (string)this["p1"]; }
        set { this["p1"] = value; }
    }
}

我想让ConfigurationSection 及其子ConfigElement 可继承。这可以使用类型参数来完成,如下所示:

public class StandardConfiguration<TChildConfig> : ConfigurationSection
    where TChildConfig : StandardChildConfig
{
    [ConfigurationProperty("childConfig")]
    public TChildConfig ChildConfig
    {
        get { return (TChildConfig)this["childConfig"]; }
        set { this["childConfig"] = value; }
    }
}

public class StandardChildConfig : ConfigurationElement
{
    [ConfigurationProperty("p1")]
    public string P1
    {
        get { return (string)this["p1"]; }
        set { this["p1"] = value; }
    }
}

但是,我认为这会阻止我从我的 DLL 中的其他类引用静态 Instance,因为我不知道子 ConfigurationElement 的最终类型。

欢迎任何关于如何更干净地实现这一点的想法或建议。

谢谢。

编辑

假设应用程序的配置中有一个&lt;customConfigSection&gt;,我可以在第一个场景中使用StandardConfiguration.GetInstance().ChildConfig.P1 来访问P1 的值。在第二种情况下,我将如何访问相同的值?我将如何实现GetInstance()

编辑 2

以下是“零编码”场景:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section
            name="customConfig"
            type="WebsiteTemplate.Config.StandardConfigruation, WebsiteTemplate"
        />
    </configSections>
    <customConfig baseProp1="a">
        <childConfig baseProp2="b" />
    </customConfig>
</configuration>

这是扩展配置的场景:

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section
            name="customConfig"
            type="WebsiteTemplate.Extended.Config.ExtendedConfigruation, WebsiteTemplate.Extended"
        />
    </configSections>
    <customConfig baseProp1="a" extendedProp1="c">
        <childConfig baseProp2="b" extendedProp2="d" />
    </customConfig>
</configuration>

【问题讨论】:

  • Instance的类型不能是ConfigurationElement?我不清楚你在问什么......
  • @Peter Ritchie - 我添加了一个我正在尝试做的示例。让我知道这是否有意义。谢谢。
  • 只需使用我的库即可github.com/aloneguid/config

标签: c# .net oop design-patterns


【解决方案1】:

在第二种情况下,StandardConfiguration.GetInstance() 没有任何意义,因为StandardConfiguraiton 是通用的。你必须使用StandardConfiguration&lt;MyChildConfig&gt;.GetInstance().ChildConfig.P1

你也许可以这样做:

public class StandardConfigurationBase : ConfigurationSection
{
    public static StandardConfigurationBase GetInstance()
    {
        return (StandardConfigurationBase) ConfigurationManager.GetSection("customConfigSection");
    }

    [ConfigurationProperty("childConfig")]
    public StandardChildConfig ChildConfig
    {
        get { return (StandardChildConfig) this["childConfig"]; }
        set { this["childConfig"] = value; }
    }
}

public class StandardConfiguration<TChildConfig> : StandardConfigurationBase
where TChildConfig : StandardChildConfig
{
    [ConfigurationProperty("childConfig")]
    public new TChildConfig ChildConfig
    {
        get { return (TChildConfig)this["childConfig"]; }
        set { this["childConfig"] = value; }
    }
}
public class StandardChildConfig : ConfigurationElement
{
    [ConfigurationProperty("p1")]
    public string P1
    {
        get { return (string)this["p1"]; }
        set { this["p1"] = value; }
    }
}

然后在不知道具体类型的时候访问孩子:

    StandardConfigurationBase b = new StandardConfiguration<StandardChildConfig>();
    StandardChildConfig x = StandardConfigurationBase.GetInstance().ChildConfig;

但是,我不清楚这样做的真正价值。

【讨论】:

  • 我正在创建一个网站模板,用于在我的公司进行分发。该模板将附带一个 DLL,并且需要基本配置。我希望这个模板的实现者能够扩展配置。将属性添加到基本配置很简单。棘手的是如何让ConfigurationSectionConfigurationElements 可以扩展。我知道每个网站都可以创建自己的配置,但我认为按照我的方式做事会让配置更干净。不过我可能错了:)
【解决方案2】:

我的问题的“答案”是将基本配置分解为具有类型参数和接口的抽象类。

下面显示了 BaseLib.dll 中定义的内容。有默认配置和默认子配置。

接口和抽象类

public interface IAppConfig
{
    string AppProp1 { get; }
    SubConfig SubConfig { get; }
}

public abstract class BaseAppConfig<TSubConfig> : ConfigurationSection, IAppConfig
    where TSubConfig : SubConfig
{
    [ConfigurationProperty("appProp1")]
    public string AppProp1
    {
        get { return (string)this["appProp1"]; }
        set { this["appProp1"] = value; }
    }

    [ConfigurationProperty("subConfig")]
    public TSubConfig SubConfig
    {
        get { return (TSubConfig)this["subConfig"]; }
        set { this["subConfig"] = value; }
    }

    // Implement the interface
    string IAppConfig.AppProp1 { get { return this.AppProp1; } }
    SubConfig IAppConfig.SubConfig { get { return this.SubConfig; } }
}

默认实现

public class AppConfig : BaseAppConfig<SubConfig>
{
    const string SECTION_KEY = "AppConfig";

    public static IAppConfig Instance
    {
        get { return (IAppConfig)ConfigurationManager.GetSection(SECTION_KEY); }
    }
}

public class SubConfig : ConfigurationElement
{
    [ConfigurationProperty("supProp1")]
    public string SubProp1
    {
        get { return (string)this["supProp1"]; }
        set { this["supProp1"] = value; }
    }
}

如何从 BaseLib.dll 访问配置

public class ArbitraryClass
{
    void DoSometing()
    {
        Console.Write(AppConfig.Instance.SubConfig.SubProp1);
    }
}

下面显示了 ExtLib.dll 中定义的内容。配置和子配置都被扩展了。

扩展实现

public class ExtAppConfig : BaseAppConfig<ExtSubConfig>
{
    public static ExtAppConfig Instance
    {
        get { return (ExtAppConfig)AppConfig.Instance; }
    }

    [ConfigurationProperty("extAppProp1")]
    public string ExtAppProp1
    {
        get { return (string)this["extAppProp1"]; }
        set { this["extAppProp1"] = value; }
    }
}

public class ExtSubConfig : SubConfig
{
    [ConfigurationProperty("extSubProp1")]
    public string ExtSubProp1
    {
        get { return (string)this["extSubProp1"]; }
        set { this["extSubProp1"] = value; }
    }
}

如何从 ExtLib.dll 访问配置

public class ExtArbitraryClass
{
    void DoSometing()
    {
        Console.Write(ExtAppConfig.Instance.SubConfig.ExtSubProp1);
    }
}

库中定义了更多内容,但它应该使扩展此配置相对容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多