Compact Frameworkで強化して欲しい点について(´д`)
現状のCompact Frameworkへの不満点について、思いつきメモ。
以下、強化して欲しい点。
Graphics周りの強化
例えば、Graphics.DrawLine()ではfloat版も使いたかったり(・ω・)
なぜかというと、Graphics.DrawLine()で1ピクセルの点を書きにくいから(゚∀゚)
同じ座標にDrawLine()だと何も描画されないし、座標を1ピクセルずらすと2ピクセルの線になってしまうけど、小数点を指定すれば1ピクセルの点が描画できるので。
まあ、今はNativeにCreatePen()して、MoveToEx()、LineTo()していたりするんだけどさ(´д`;)
マーシャリングの強化
とりあえずStructLayoutAttribute.Packを(´・ω・`)
こいつがサポートされないせいで、今はリフレクションを使ったbyte配列変換*1を使用しているわけですが(´д`;)
ハンディーターミナルのアプリでは、PCサーバ(っというか、その背後の基幹システム)から降ってきた固定長データファイルをマスタとして使うような事もするので。
Control.WndProcの標準サポート
どうせSetWindowLong()する事になるんだから、標準でサポートしてよ(´・ω・`)
まあ、とりあえずNative APIレベルでサポートしていることは、一通りサポートして欲しいと思ったりするわけですが(´Д`)
っで、ここまでは、現状でもとりあえず代替手段がある内容。
現状ではちょっとな〜と思うのが次の内容。
System.Linq.Expressionのサポート
System.Linq.Expressionがあれば、こういうことが出来るので(`・ω・´)
class Hoge { public int Param { get; set; } } private static void SetValueToProperty<T>(T target, Expression<Func<T, object>> func) { PropertyInfo pi = typeof(T).GetProperty( ((MemberExpression)func.Body).Member.Name ); pi.SetValue( target, 123, null ); } static void Main() { Hoge target = new Hoge(); SetValueToProperty( target, x => x.Param ); // x => x.ParamでPropertyInfoを指定したい System.Diagnostics.Debug.Assert( target.Param == 123 ); }
要するに、LINQモドキ的な事がやりたいというか、安全にPropertyInfoを指定したいだけですが(´д`;)
文字列で"Param"を指定したくないと言うだけのことなんですけどね。
いっそ、fieldof()、propertyof()、methodof()みたいなものが使えるようになるというんでも良いけど(・∀・)
こういうものの言語レベルでのサポートが無いせいで、JavaとかのLINQ似せライブラリでは、メタ情報の定義が冗長だったり、ちょっとトリッキーな実装になっていたりね〜(´Д`)
例えば、jaquなんかでもこういうコードは書けるわけですが。
import org.h2.jaqu.Table; import static org.h2.jaqu.Define.*; public class Product implements Table { public Integer productId; public String productName; public String category; public Double unitPrice; public Integer unitsInStock; public void define() { tableName("Product"); primaryKey(productId); index(productName, category); } }
Db db = Db.open( ... ); Product p = new Product(); List<Product> list = db.from(p). where(p.productId).is(1). select();
where()の所でproductIdを指定しているけど、それって値ですよね(゚Д゚)?、そこからどうしてSQLの列名(の元になるField情報)を作れるんですか( ゚д゚)?、っと言うことになるわけですが。
仕掛けはfrom()の中で行っているインスタンスへの初期化処理にあって、その中でインスタンスの各フィールドに対してユニークな値を設定することにより、その値からField情報を引けるようにしているんですよね(゜Д゜;)
例えば、以下の様な処理を実行してみると何をしているかがわかります。
Product p = new Product();
Query<Product> query = db.from(p);
from()メソッドの実行後にpの各メンバを見てみると、{ productId = Integer(5), productName = String("6"), category = String("7"), unitPrice = Double(8.0), unitsInStock = Integer(9) }みたいな値が設定されています。
これにより、where(p.productId)→where(5)が呼び出されると、5に対応するのはproductIdのField情報と言うことがわかり、そこからSQLの列名を作ることができるというような仕掛けになっています(・ω・)
また、インスタンス初期化ブロックを使ってselect()でこういうことも出来たりね(・∀・)
final Customer c = new Customer(); final Order o = new Order(); List<CustOrder> orders = db.from(c). innerJoin(o).on(c.customerId).is(o.customerId). select(new CustOrder() {{ customerId = c.customerId; orderId = o.orderId; total = o.total; }});
まあ、こういうトリッキーな方法ではなくて、別途メタ情報を用意するっていうんでも良いんですが、言語レベルでのExpressionsのサポートが無い言語では、どうやるのがスマートなのかな〜っと考えてみたりして(´-`)
なんか、Compact Frameworkの話からjaquの話にズレちった(・ω・)
*1:カスタム属性でオフセットとサイズを指定して、その情報を元にクラスメンバ/byte配列の相互変換を行う。