假设我有以下配置部分....
<yak>
<whaa hello="world" />
</yak>
<yak>
<whaa hello="world" blot="1" />
</yak>
因为第二个<whaa>
元素上有额外的属性,我想将它映射到映射到第一个<whaa>
元素的类型的子类型。
那么我如何获得多态绑定?
答案 0 :(得分:2)
这是使用编程解决方案的一种方法,该解决方案会覆盖OnDeserializeUnrecognizedElement
类的ConfigurationSection
方法。基本和子配置元素类:
public class Whaa : ConfigurationElement
{
[ConfigurationProperty("hello", IsRequired = true)]
public string Hello
{
get
{
return base["hello"] as string;
}
set
{
base["hello"] = value;
}
}
}
public class WhaaChild : Whaa
{
[ConfigurationProperty("blot", IsRequired = true)]
public string Blot
{
get
{
return base["blot"] as string;
}
set
{
base["blot"] = value;
}
}
}
配置部分类:
public class Yak : ConfigurationSection
{
public Whaa MyProperty;
protected override bool
OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
{
if (elementName == "whaa")
{
try
{
var hello = reader.GetAttribute("hello");
if (hello != null)
{
var blot = reader.GetAttribute("blot");
if (blot != null)
{
MyProperty = new WhaaChild()
{
Blot = blot,
Hello = hello
};
}
else
{
MyProperty = new Whaa()
{
Hello = hello
};
}
}
}
catch (Exception)
{
// TODO: add exception handling
}
}
return true;
}
}
样本用法:
var yakSectionSettings = (Yak)ConfigurationManager.GetSection("yak");
配置标记:
<configSections>
<section name="yak" type="Yak, MyApplication"/>
</configSections>
您现在可以使用:
<yak>
<whaa hello="world"/>
</yak>
获取Whaa
个对象,或者:
<yak>
<whaa hello="world" blot="1"/>
</yak>
用于在运行时获取WhaaChild
对象。
答案 1 :(得分:0)
This解决方案使用Proxy类包装子类型的实现。底部有一条评论,甚至提到针对不同的子类型以不同的方式命名集合元素,因此遵循以下原则:
<yak>
<whaa hello="world" />
</yak>
<yak>
<whaaChild hello="world" blot="1" />
</yak>
在下面摘录以防万一链接消失,但是请先尝试链接以支持他们的博客!
NestedConfiguration.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Xml;
namespace NestedConfiguration
{
public class CollectionSection : ConfigurationSection
{
[ConfigurationProperty("collection", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(CollectionConfig), AddItemName = "add")]
public CollectionConfig Collection
{
get
{
return (CollectionConfig) this["collection"];
}
set
{
this["collection"] = value;
}
}
}
public class Parent : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get
{
return (string) this["name"];
}
set
{
this["name"] = value;
}
}
[ConfigurationProperty("type", IsRequired = true)]
public string Type
{
get
{
return (string) this["type"];
}
set
{
this["type"] = value;
}
}
public void ProxyDeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
DeserializeElement(reader, serializeCollectionKey);
}
}
public class One : Parent
{
[ConfigurationProperty("p1")]
public string P1
{
get
{
return (string)this["p1"];
}
set
{
this["p1"] = value;
}
}
}
public class Two : Parent
{
[ConfigurationProperty("p2")]
public string P2
{
get
{
return (string)this["p2"];
}
set
{
this["p2"] = value;
}
}
}
public class Proxy : ConfigurationElement
{
private Parent _Parent = null;
public Parent Parent
{
get
{
return _Parent;
}
}
public Proxy()
{
}
public Parent Instance
{
get
{
return _Parent;
}
}
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
string type = reader.GetAttribute("type");
switch (type)
{
case "one":
_Parent = new One();
break;
case "two":
_Parent = new Two();
break;
default:
throw new ArgumentException(string.Format("Invalid type: {0}", type));
}
_Parent.ProxyDeserializeElement(reader, serializeCollectionKey);
}
}
public class CollectionConfig : ConfigurationElementCollection
{
public CollectionConfig()
{
}
protected override ConfigurationElement CreateNewElement()
{
return new Proxy();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((Proxy)element).Parent.Name;
}
public Parent this[int index]
{
get
{
return ((Proxy)BaseGet(index)).Parent;
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="CollectionSection" type="NestedConfiguration.CollectionSection, NestedConfiguration" />
</configSections>
<CollectionSection>
<collection>
<add type="one" name="one-1" p1="one-1 p1" />
<add type="one" name="one-2" p1="one-2 p1" />
<add type="two" name="two-1" p2="two-1 p2" />
</collection>
</CollectionSection>
</configuration>
Program.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
namespace NestedConfiguration
{
class Program
{
static void Main(string[] args)
{
try
{
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "NestedConfiguration.exe.config";
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
CollectionSection config = (CollectionSection)configuration.Sections[typeof(CollectionSection).Name];
Console.WriteLine("Nested configurations: {0}", config.Collection.Count);
foreach (Proxy proxy in config.Collection)
{
Console.WriteLine("Type: {0}", proxy.Parent.GetType());
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}