お知らせがあります。
それは実際に可能です...しかし!(はい、ありますが)。
動的Linqライブラリを使用していると思います。次に、「it」キーワードを使用して、インデックス作成操作を適用する現在のオブジェクトを指定できるようにする必要があります。
ただし...インデクサーの戻りデータ型はオブジェクトであるため、データ型が一致しないため、[0]>100および[1]="wpf"と書き込むことはできません。
また、DynamicObjectから派生し、実行時にプロパティを追加する場合でも、それらのプロパティは、現在の状態の動的linqライブラリによって実行時に解決されません。フィールドを取得するか、プロパティがタイプxxxに存在しません。
これにはいくつかの解決策があり、そのうちのいくつかは解決策として受け入れることができます。
醜い解決策の1つは、データ型の数が限られている場合、たとえばn(n <.NETの型の数)の場合、パラメーターが一致するn個のインデクサーを使用して、必要なデータ型を取得できます。たとえば、主にintといくつかの文字列がある場合:
it[0] > 100 AND it[1, "dummy"] = "wpf" //The dummy parameter allows you to specify return type.
もう1つの醜い解決策であるDynamicLinqは、ToString()メソッドとConvertメソッドの使用をサポートしているため、たとえば、上記と同じクエリを記述できます。
Convert.ToDouble(it[0]) > 100 AND it[1].ToString() = "wpf".
3番目の醜い解決策は、データを変換する方法を指示する方法でステートメントをラップする規則を使用できます。たとえば、次のように書くことができます。
it[0] > 100 AND it{1} = "wpf"
そして、「it[」を「Convert.ToDouble(it[」などに置き換えます。
私が正しければ、ライブラリで汎用インデクサーを使用することもできないと思います。そして、Convert.ChangeTypeは、戻り型がまだオブジェクトであるため、この場合は役に立ちません。
たぶん私や他の誰かがこの種のことをサポートするためにいつかライブラリを書き直すでしょうが、近い将来(数週間)はそうする時間がありません。
申し訳ありませんが、15分以内にどこかに行かなければならないので、後でもっと良い解決策を講じる必要があります。
会議に自分をテレポートする
アップデート:
私はあなたの(そして私の)問題の解決策を見つけたかもしれないと思います!
DLINQライブラリでは、操作できるようにするタイプのメンバーをIxxxSignaturesインターフェースに追加できます。
そこで、(たとえば)IEqualitySignaturesに次のように追加しました。
void F(Object x, Int32 y);
そして、このようにelseブロックの(この場合)ParseComparisonメソッドを変更しました。
left = Expression.Convert(left, right.Type);
そして、信じられないかもしれませんが、うまくいきました:)
他のタイプや操作の署名を追加していないため、すべての種類の操作をテストしたわけではありませんが、実行するのは非常に簡単です。
アップデート
上記のいくつかのマイナーなものを更新しました。
私はこれについてもう少し実験しています。これも最も美しい解決策ではないかもしれませんが、次のようなことを行うことができます(DataObjectはインデクサーを備えた単なるDynamicObjectです)。
[TestMethod]
public void DynamicTest()
{
List<DataObject> dataObjects = new List<DataObject>();
dynamic firstObject = new DataObject();
dynamic secondObject = new DataObject();
firstObject.dblProp = 10.0;
firstObject.intProp = 8;
firstObject.strProp = "Hello";
secondObject.dblProp = 8.0;
secondObject.intProp = 8;
secondObject.strProp = "World";
dataObjects.Add(firstObject);
dataObjects.Add(secondObject);
/* Notice the different types */
string newQuery = FormatQuery("dblProp > 9.0 AND intProp = 8 AND strProp = 'Hello'");
var result = dataObjects.Where(newQuery);
Assert.AreEqual(result.Count(), 1);
Assert.AreEqual(result.First(), firstObject);
}
そして、次のようなある種のフォーマットメソッド(完全なメソッドを作成したふりをします):
public string FormatQuery(string query)
{
query = query.Replace('\'', '\"');
string[] operators = new string[] { "<", ">", "!=", "<=", ">=", "<>", "=" };
string[] parts = query.Split();
for (int i = 0; i < parts.Length; i++)
{
if (operators.Contains(parts[i]))
{
parts[i - 1] = "it[\"" + parts[i - 1] + "\"]";
}
}
return String.Join(" ", parts);
}
もちろん、代わりに拡張メソッドを使用することもできます。
または...次のようなものを使用して、メソッドをDLINQ libに配置できます(ただし、良いアイデアとは言えません)。
if (typeof(T).GetInterface("IDynamicMetaObjectProvider", true) != null)
whereClause = whereClause.FormatQuery();
そして、タイプが文字列インデクサーを実装しているかどうかを確認します。もちろん、次のようになります(ここではIndexerName属性を無視します)。
if (t.GetType().GetProperty("Item") != null)
これにより、「通常のユーザー」は次のように書くことができます。
data.Where("dblProp > 9.0 AND intProp = 8 AND strProp = 'Hello'")
ええと、そこにそのようなものを入れるのは良くないかもしれませんが、あなたは要点を理解します。あなたが持つことができます!:)