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配列の相互変換を行う。