c#4.0 dynamicの使い方です。この機能は知らなかったです。
Test1 ... dynamic型
Test2 ... Dycnamicクラス
Test3 ... reflectionとの対比
using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { public class Test1 { public class Order { public int ProductID { get; set; } public int Quantity { get; set; } } // dynamic型 public static void PMain() { Order o1 = new Order(); o1.ProductID = 100; o1.Quantity = 1; //o1.Description = 0;//コンパイルエラー(メンバがないため) object o2 = new Order(); //o2.ProductID = 100; o2.Quantity = 1;//コンパイルエラー(メンバがないため) try { dynamic o4 = new Order(); o4.ProductID = 100; //★ dynamic型なのでコンパイル通過する o4.Quantity = 1; //! 欠点はtypo検出できない、実行時の負荷大きいなど String str = String.Format("{0},{1}", o4.ProductID, o4.Quantity); Console.WriteLine("{0}", str); } catch { Console.WriteLine("dame"); } } } // DynamicObjectクラス public class Test2 { public class Statictics1 { public int TotalAmount { get; set; } public int TotalQuantity{ get; set;} public Statictics1() { TotalAmount = 0; TotalQuantity = 0; } public void Add( dynamic order) { TotalAmount += (order.Amount ?? 0); TotalQuantity += (order.Quantity ?? 0); } } public class Order : DynamicObject { private Dictionary<string, object> items = new Dictionary<string, object>(); private const object MyDefault = null; public override bool TrySetMember(SetMemberBinder binder, object value) { string name = binder.Name; if (binder.IgnoreCase) { name = name.ToLower(); } items[name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { string name = binder.Name; if (binder.IgnoreCase) { name = name.ToLower(); } if (!items.TryGetValue(name, out result)) { result = MyDefault; } return true; } } public static void PMain() { dynamic o1 = new Order(); o1.ProductID = 100;//仮想関数が呼ばれる o1.Quantity = 1; dynamic o3 = new Order(); o3.ProductID = 300; o3.Refund = 1000; try { Statictics1 stat = new Statictics1(); stat.Add(o1); stat.Add(o3); Console.WriteLine("{0}: {1} ", stat.TotalAmount, stat.TotalQuantity); } catch { Console.WriteLine("dame"); } } } // リクレクションとdynamicの比較 public class Test3 { public class Transport { public string Name { get; set; } public string How { get; set; } public Transport(string n, string h ) { Name = n; How = h; } } public class UseReflection { public static void PMain() { Transport[] transports ={ new Transport("001","Land"), new Transport("002","Sea"), new Transport("003","Sea"), new Transport("004","Land"), new Transport("005","Air"), }; var q1 = from t in transports where t.How == "Land" select new { Name = t.Name, Kind = t.How }; foreach (var t in q1) { Print1(t); } foreach (var t in q1) { Print2(t); } } static public void Print1(object o1) { Type type = o1.GetType(); PropertyInfo info1 = type.GetProperty("Name"); PropertyInfo info2 = type.GetProperty("Kind"); if (info1 == null || info2 == null) { return ; } object name = info1.GetValue(o1, null) ?? ""; object kind = info2.GetValue(o1, null) ?? ""; Console.WriteLine("{0}:{1}",name, kind); } //★Print1よりも、とても簡単にかけます。 static public void Print2(dynamic o2 ){ try{ Console.WriteLine("{0} : {1}", o2.Name, o2.Kind); }catch(Exception){ } } } } public class Program { public static void Main(string[] args) { // Test1.PMain(); // Test2.PMain(); Test3.UseReflection.PMain(); } } }