WPFのXAMLではTypeConverterを自作して文字列から、オブジェクトを作るようなことが簡単にできるようになっています。ということで簡単に試してみました。XAMLからオブジェクトへの変換にはTypeConverterクラスのConvertFromメソッドとCanConvertFromメソッドを実装していれば問題なさそう。
今回は以下のようなPersonクラスで
publicclass Person { publicstring Name { get; set; } public Person Child { get; set; } }
Tanaka->Kimura->Hoge->Fooみたいに入力するとNameがTnakaのPersonを作って、そのChildにNameがKimuraのPersonを作って、そのChildに…(略)となるようなTypeConverterを作りました。->で区切って組み立てていくだけですので簡単です。
publicclass PersonTypeConverter : TypeConverter { publicoverridebool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string); } publicoverrideobject ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, objectvalue) { 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))] publicclass Person { publicstring Name { get; set; } public Person Child { get; set; } }
System.Xamlを参照してレッツパース。
class Program { staticvoid 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 { staticvoid 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))] publicclass Person { publicstring Name { get; set; } public Person Child { get; set; } } publicclass PersonTypeConverter : TypeConverter { publicoverridebool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string); } publicoverrideobject ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, objectvalue) { 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(); } } }