WPFのXAMLではTypeConverterを自作して文字列から、オブジェクトを作るようなことが簡単にできるようになっています。ということで簡単に試してみました。XAMLからオブジェクトへの変換にはTypeConverterクラスのConvertFromメソッドとCanConvertFromメソッドを実装していれば問題なさそう。
今回は以下のようなPersonクラスで
public class Person { public string Name { get; set; } public Person Child { get; set; } }
Tanaka->Kimura->Hoge->Fooみたいに入力するとNameがTnakaのPersonを作って、そのChildにNameがKimuraのPersonを作って、そのChildに…(略)となるようなTypeConverterを作りました。->で区切って組み立てていくだけですので簡単です。
public class PersonTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var text = (string)value; var people = text .Split(new[] { "->" }, StringSplitOptions.None) .Select(s => s.Trim()) .Select(s => new Person { Name = s }) .ToArray(); people .Aggregate((parent, child) => { parent.Child = child; return child; }); return people.First(); } }
このコンバータをPersonクラスにつけます。
[TypeConverter(typeof(PersonTypeConverter))] public class Person { public string Name { get; set; } public Person Child { get; set; } }
System.Xamlを参照してレッツパース。
class Program { static void Main(string[] args) { var xaml = @" <Person xmlns='clr-namespace:ConsoleApplication3;assembly=ConsoleApplication3' Name='Tanaka taro' Child='Tanaka goro->Tanaka jiro->Tanaka hoge->Tnaka foo' /> "; var p = XamlServices.Parse(xaml) as Person; while (p != null) { Console.WriteLine("Name: {0}", p.Name); p = p.Child; } } }
実行するといい感じに表示されます。
Name: Tanaka taro Name: Tanaka goro Name: Tanaka jiro Name: Tanaka hoge Name: Tnaka foo
コード全体
最後にコード全体をのせておきます。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xaml; namespace ConsoleApplication3 { class Program { static void Main(string[] args) { var xaml = @" <Person xmlns='clr-namespace:ConsoleApplication3;assembly=ConsoleApplication3' Name='Tanaka taro' Child='Tanaka goro->Tanaka jiro->Tanaka hoge->Tnaka foo' /> "; var p = XamlServices.Parse(xaml) as Person; while (p != null) { Console.WriteLine("Name: {0}", p.Name); p = p.Child; } } } [TypeConverter(typeof(PersonTypeConverter))] public class Person { public string Name { get; set; } public Person Child { get; set; } } public class PersonTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var text = (string)value; var people = text .Split(new[] { "->" }, StringSplitOptions.None) .Select(s => s.Trim()) .Select(s => new Person { Name = s }) .ToArray(); people .Aggregate((parent, child) => { parent.Child = child; return child; }); return people.First(); } } }