Xelementを使用した降下
-
21-09-2019 - |
質問
XmlserializerとdatAcontractSerializerが私のニーズに合っていないため、私は自分の脱介器を書かなければなりませんでした。だから、これが私の脱介入の基盤です:
static BaseElement ParseXml(XElement element)
{
var e = (Element)Activator.CreateInstance(Type.GetType("Elements." + element.Name));
foreach (var attr in element.Attributes())
{
var property = e.GetType().GetProperty(attr.Name.LocalName);
property.SetValue(e, Convert.ChangeType(attr.Value, property.PropertyType), null);
}
foreach (var x in element.Elements())
e.Elements.Add(ParseXml(x));
return e;
}
ベースエレメントクラス:
public abstract class BaseElement
{
public BaseElement()
{
Elements = new List<Element>();
}
public IList<Element> Elements
{
get;
set;
}
}
唯一の制限は、convert.changeTypeを使用してカスタムタイプに変換できないため、カスタムと入力された属性を持つことができないことです。これを解決する方法についてのアイデアはありますか?
ありがとう。
解決
あなたは、 IConvertible
インターフェース。 これがそうです MSDNの例。
他のヒント
Iconvertibleは、この場合に必要なタイプのインスタンスを作成するために文字列を使用する方法を定義しません。コンバージョンコンストラクターを作成できますが、面倒なことに、何らかの理由で反射を介して値を設定しようとすると、自動的に呼び出されます。そのため、コンバージョンコンストラクターを手動で検索し、該当する場合は呼び出す必要があります。これは私がそれをする方法についてです:
namespace Elements
{
class Program
{
static void Main(string[] args)
{
System.Xml.Linq.XElement sample = System.Xml.Linq.XElement.Parse(
"<Element a=\"3\" b=\"Havarti\" modeSel=\"Complex\" />");
Element c1 = Element.ParseXml(sample);
}
}
public class ModeSelection
{
private int mode;
public static explicit operator ModeSelection(string value)
{
ModeSelection result = new ModeSelection();
if (String.Compare(value, "Simple", true) == 0)
result.mode = 1;
else if (String.Compare(value, "Complex", true) == 0)
result.mode = 2;
else if (!int.TryParse(value, out result.mode))
throw new FormatException("Cannot convert value to type " + result.GetType().Name);
return result;
}
string Description
{
get
{
switch (mode)
{
case 1:
return "Simple";
case 2:
return "Complex";
default:
return "Other";
}
}
}
}
public abstract class BaseElement<T> where T : BaseElement<T>, new()
{
public static T ParseXml(System.Xml.Linq.XElement element)
{
var e = (T)Activator.CreateInstance(Type.GetType("Elements." + element.Name));
Type[] convParamTypes = new Type[] {typeof(string)};
foreach (var attr in element.Attributes())
{
var property = e.GetType().GetProperty(attr.Name.LocalName);
System.Reflection.MethodInfo conv = property.PropertyType.GetMethod(
"op_Explicit", convParamTypes);
if (conv != null)
property.SetValue(e, conv.Invoke(null, new object[] {attr.Value}), null);
else
property.SetValue(e, Convert.ChangeType(attr.Value, property.PropertyType), null);
}
foreach (var x in element.Elements())
e.Elements.Add(ParseXml(x));
return e;
}
public BaseElement()
{
Elements = new List<T>();
}
public IList<T> Elements
{
get;
set;
}
}
public class Element : BaseElement<Element>
{
int _a;
string _b;
ModeSelection _modeSel;
public int a
{
get
{
return _a;
}
set
{
_a = value;
}
}
public string b
{
get
{
return _b;
}
set
{
_b = value;
}
}
public ModeSelection modeSel
{
get
{
return _modeSel;
}
set
{
_modeSel = value;
}
}
}
}
所属していません StackOverflow