如何从 xml 获取接口类型的对象列表
How to get a list of objects which are interface type from xml
如何从 xml:
得到 List<IntrfaceType>
<?xml version="1.0" encoding="utf-8" ?>
<processSettings>
<processName>chrome.exe</processName>
<location>L1</location>
<watch>true</watch>
<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>
</processSettings>
我试过这样:
[XmlRootAttribute("rules", Namespace = "", IsNullable = false)]
public class Rules
{
[XmlArrayItem("autoStart", Type = typeof(AutoStart)),
XmlArrayItem("noMore", Type = typeof(NoMore)),
XmlArrayItem("unExpectedCrush", Type = typeof(UnExpectedCrush))]
public Rule[] RuleItems;
XmlSerializer ruleSerializer = new XmlSerializer(typeof(Rule[]), new XmlRootAttribute("rules"));
Rule[] rules = (Rule[])ruleSerializer.Deserialize(config.Rules.CreateReader());
在本例中Rule : IRule
和AutoStart, NoMore, UnExpectedCrush : Rule
,所以我想得到Rule[]
然后转换它List<IRule>
,但是Deserialize
returns一个空数组。所以请帮助理解我做错了什么。
好的,所以我认为您要做的是将所有内容映射到:
<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>
到规则列表。你只是想 运行 直接在 XML 上反序列化,并假设它会神奇地将 rules
的 children 映射到 IRule
.
如果你真的想要一个规则列表,你首先必须以某种方式提取信息。这最容易通过将 XML 映射到类型化的 object 来完成。因此,在您的情况下,我不会以列表结尾,而是进行映射 object:
public class Rules
{
public string AutoStart { get; set; }
public string NoMore { get; set; }
public string UnExpectedCrush { get; set; }
}
所以做这样的事情:
(Rules) ruleSerializer.Deserialize(config.Rules.CreateReader());
现在您有了一个 object,其中列出了您的所有规则。从那时起,您可以将属性重新映射到规则列表中。但我认为有一个实际的规则 object,其中规则被命名,对于可能阅读您的代码的其他人来说通常更清楚。那只是我的两分钱。
或者: 如果您可以控制 XML,您可以这样做:
<processSettings>
<processName>chrome.exe</processName>
<location>L1</location>
<watch>true</watch>
<rules>
<rule>autoStart</rule>
<rule>noMore</rule>
<rule>unExpectedCrush</rule>
</rules>
</processSettings>
并将其反序列化为规则列表:
(List<Rule>)deserializer.Deserialize(config.Rules.CreateReader());
然后你就有了可以翻译成它的界面版本的规则列表。
但这会改变 XML,因此它假定您可以控制它。
编辑: List<Rule>
到 List<IRule>
因此,如果您能够获得 List<Rule>
的列表并且 Rule 具有相关接口。然后你可以转换你的 List<Rule>
:
List<Rule> rules = new List<Rule>();
List<IRule> iRules = rules.ToList<IRule>();
取自这个答案Whosebug answer
EDIT2: 将 XElement 序列化为规则列表:
好的,所以我仍然很难理解为什么您需要将这些规则映射到 object 而不是具有值的规则。我会说一个规则列表,其中包含一个字符串,说明它是哪种规则将使您的生活更轻松。然后你只需要进行字符串比较,看看你有什么规则。
所以我认为这将解决您的问题:
public List<IRule> GetListOfRules()
{
var rulesElement = XElement.Parse(@"<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>");
var listOfRulesFromElement =
rulesElement.Elements().Select(d => new Rule { RuleName = d.Name.LocalName }).ToList<IRule>();
return listOfRulesFromElement;
}
public class Rule : IRule
{
public string RuleName { get; set; }
public string GetRule()
{
return RuleName;
}
}
public interface IRule
{
string GetRule();
}
使用此代码,您的结构和规则之间没有任何硬耦合。您只需向 XML 元素添加新规则,它就会自动添加到您的规则列表中。然后你可以检查规则列表,看看有哪些基于 RuleName
的规则。希望这就是你想要的。
编辑 3:类型映射:
如果您需要类型映射,我建议使用枚举:
public List<IRule> GetListOfRules()
{
var rulesElement = XElement.Parse(@"<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>");
var listOfRulesFromElement =
rulesElement.Elements().Select(d =>
{
var parsed = Enum.TryParse(d.Name.LocalName, out RuleType ruleName);
if (!parsed)
ruleName = RuleType.UnmappedRule;
return new Rule {RuleName = ruleName};
}).ToList<IRule>();
return listOfRulesFromElement;
}
public class Rule : IRule
{
public RuleType RuleName { get; set; }
public RuleType GetRule()
{
return RuleName;
}
}
public enum RuleType
{
UnmappedRule,
AutoStart,
NoMore,
UnExpectedCrush
}
public interface IRule
{
RuleType GetRule();
}
如何从 xml:
得到List<IntrfaceType>
<?xml version="1.0" encoding="utf-8" ?>
<processSettings>
<processName>chrome.exe</processName>
<location>L1</location>
<watch>true</watch>
<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>
</processSettings>
我试过这样:
[XmlRootAttribute("rules", Namespace = "", IsNullable = false)]
public class Rules
{
[XmlArrayItem("autoStart", Type = typeof(AutoStart)),
XmlArrayItem("noMore", Type = typeof(NoMore)),
XmlArrayItem("unExpectedCrush", Type = typeof(UnExpectedCrush))]
public Rule[] RuleItems;
XmlSerializer ruleSerializer = new XmlSerializer(typeof(Rule[]), new XmlRootAttribute("rules"));
Rule[] rules = (Rule[])ruleSerializer.Deserialize(config.Rules.CreateReader());
在本例中Rule : IRule
和AutoStart, NoMore, UnExpectedCrush : Rule
,所以我想得到Rule[]
然后转换它List<IRule>
,但是Deserialize
returns一个空数组。所以请帮助理解我做错了什么。
好的,所以我认为您要做的是将所有内容映射到:
<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>
到规则列表。你只是想 运行 直接在 XML 上反序列化,并假设它会神奇地将 rules
的 children 映射到 IRule
.
如果你真的想要一个规则列表,你首先必须以某种方式提取信息。这最容易通过将 XML 映射到类型化的 object 来完成。因此,在您的情况下,我不会以列表结尾,而是进行映射 object:
public class Rules
{
public string AutoStart { get; set; }
public string NoMore { get; set; }
public string UnExpectedCrush { get; set; }
}
所以做这样的事情:
(Rules) ruleSerializer.Deserialize(config.Rules.CreateReader());
现在您有了一个 object,其中列出了您的所有规则。从那时起,您可以将属性重新映射到规则列表中。但我认为有一个实际的规则 object,其中规则被命名,对于可能阅读您的代码的其他人来说通常更清楚。那只是我的两分钱。
或者: 如果您可以控制 XML,您可以这样做:
<processSettings>
<processName>chrome.exe</processName>
<location>L1</location>
<watch>true</watch>
<rules>
<rule>autoStart</rule>
<rule>noMore</rule>
<rule>unExpectedCrush</rule>
</rules>
</processSettings>
并将其反序列化为规则列表:
(List<Rule>)deserializer.Deserialize(config.Rules.CreateReader());
然后你就有了可以翻译成它的界面版本的规则列表。
但这会改变 XML,因此它假定您可以控制它。
编辑: List<Rule>
到 List<IRule>
因此,如果您能够获得 List<Rule>
的列表并且 Rule 具有相关接口。然后你可以转换你的 List<Rule>
:
List<Rule> rules = new List<Rule>();
List<IRule> iRules = rules.ToList<IRule>();
取自这个答案Whosebug answer
EDIT2: 将 XElement 序列化为规则列表:
好的,所以我仍然很难理解为什么您需要将这些规则映射到 object 而不是具有值的规则。我会说一个规则列表,其中包含一个字符串,说明它是哪种规则将使您的生活更轻松。然后你只需要进行字符串比较,看看你有什么规则。
所以我认为这将解决您的问题:
public List<IRule> GetListOfRules()
{
var rulesElement = XElement.Parse(@"<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>");
var listOfRulesFromElement =
rulesElement.Elements().Select(d => new Rule { RuleName = d.Name.LocalName }).ToList<IRule>();
return listOfRulesFromElement;
}
public class Rule : IRule
{
public string RuleName { get; set; }
public string GetRule()
{
return RuleName;
}
}
public interface IRule
{
string GetRule();
}
使用此代码,您的结构和规则之间没有任何硬耦合。您只需向 XML 元素添加新规则,它就会自动添加到您的规则列表中。然后你可以检查规则列表,看看有哪些基于 RuleName
的规则。希望这就是你想要的。
编辑 3:类型映射:
如果您需要类型映射,我建议使用枚举:
public List<IRule> GetListOfRules()
{
var rulesElement = XElement.Parse(@"<rules>
<autoStart></autoStart>
<noMore></noMore>
<unExpectedCrush></unExpectedCrush>
</rules>");
var listOfRulesFromElement =
rulesElement.Elements().Select(d =>
{
var parsed = Enum.TryParse(d.Name.LocalName, out RuleType ruleName);
if (!parsed)
ruleName = RuleType.UnmappedRule;
return new Rule {RuleName = ruleName};
}).ToList<IRule>();
return listOfRulesFromElement;
}
public class Rule : IRule
{
public RuleType RuleName { get; set; }
public RuleType GetRule()
{
return RuleName;
}
}
public enum RuleType
{
UnmappedRule,
AutoStart,
NoMore,
UnExpectedCrush
}
public interface IRule
{
RuleType GetRule();
}