我正在使用.NET配置API编写自定义配置部分。我想定义一个可以只有两个子元素之一的部分,
e.g。
<MyCustomSection>
<myItems>
<myItemType name="1">
<firstSubTypeConfig />
</myItemType>
<myItemType name="2">
<secondSubTypeConfig />
</myItemType>
</myItems>
</MyCustomSection>
目前,我的章节定义如下:
public class MyCustomSection : ConfigurationSection
{
public override bool IsReadOnly()
{
return false;
}
[ConfigurationProperty("myItems")]
public MyItemsCollection MyItems
{
get { return (MyItemsCollection)base["myItems"]; }
set { base["myItems"] = value; }
}
}
[ConfigurationCollection(typeof(MyItemType), AddItemName="myItemType",
CollectionType=ConfigurationElementCollectionType.BasicMap)]
public class MyItemsCollection : ConfigurationElementCollection
{
public override bool IsReadOnly()
{
return false;
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}
protected override string ElementName
{
get { return "myItemType"; }
}
protected override ConfigurationElement CreateNewElement()
{
return new MyItemType();
}
protected override object GetElementKey(ConfigurationElement element)
{
return (element as MyItemType).Name;
}
}
public class MyItemType : ConfigurationElement
{
public override bool IsReadOnly()
{
return false;
}
[ConfigurationProperty("name", IsRequired=true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
[ConfigurationProperty("firstSubTypeConfig")]
public FirstSubTypeConfig FirstSubTypeConfig
{
get { return (FirstSubTypeConfig)base["firstSubTypeConfig"]; }
set { base["firstSubTypeConfig"] = value; }
}
[ConfigurationProperty("secondSubTypeConfig")]
public SecondSubTypeConfig SecondSubTypeConfig
{
get { return (SecondSubTypeConfig)base["secondSubTypeConfig"]; }
set { base["secondSubTypeConfig"] = value; }
}
}
public class FirstSubTypeConfig : ConfigurationElement
{
public override bool IsReadOnly()
{
return false;
}
}
public class SecondSubTypeConfig : ConfigurationElement
{
public override bool IsReadOnly()
{
return false;
}
}
配置也是以编程方式修改和保存的,目前正在保存 配置部分将添加secondSubTypeConfig元素,即使我只指定了 firstSubTypeConfig元素。
我的第一个想法是为FirstSubTypeConfig
和SecondSubTypeConfig
引入一个公共基类,但我不清楚配置api是否或如何处理它。
如何设置互斥的自定义配置元素?
答案 0 :(得分:1)
我不确定这是“正确的”方法,但这很有效。
问题中编写的代码将加载配置文件。您可以检查ElementInformation.IsPresent
属性以验证是否包含一个元素。
e.g。
var custom = (MyCustomSection)ConfigurationManager.GetSection("MyCustomSection");
foreach (MyItemType itemType in custom.MyItems)
{
if (itemType.FirstSubTypeConfig.ElementInformation.IsPresent
&& itemType.SecondSubTypeConfig.ElementInformation.IsPresent)
{
throw new ConfigurationErrorsException("At most one of firstSubTypeConfig or secondSubTypeConfig can be specified in a myItemType element");
}
else if (!itemType.FirstSubTypeConfig.ElementInformation.IsPresent
&& !itemType.SecondSubTypeConfig.ElementInformation.Ispresent)
{
throw new ConfigurationErrorsException("Either a firstSubTypeConfig or a secondSubTypeConfig element must be specified in a myItemType element");
}
}
至于保存配置,似乎检查ElementInformation.IsPresent
并明确将其设置为null
将阻止该元素被写入配置文件。 e.g。
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var custom = (MyCustomSection)config.GetSection("MyCustomSection");
//make modifications against the custom variable ...
foreach (MyItemType itemType in custom.MyItems)
{
if (!itemType.FirstSubTypeConfig.ElementInformation.IsPresent)
itemType.FirstSubTypeConfig = null;
if (!itemType.SecondSubTypeConfig.ElementInformation.IsPresent)
itemType.SecondSubTypeConfig = null;
}
config.Save();
答案 1 :(得分:0)
我认为您应该使用PostDeserialize
类中提出的ConfigurationElement
方法执行此操作,而不要在您的业务逻辑上执行此操作。
例如:
protected override void PostDeserialize()
{
base.PostDeserialize();
if (FirstSubTypeConfig != null && SecondTypeCOnfig != null)
{
throw new ConfigurationErrorsException("Only an element is allowed.");
}
}