dynamic
C#4.0オブジェクトのプロパティを、実行時にしかわからないプロパティの名前で変更する方法を探しています。
次のようなことを行う方法はありますか(ExpandoObject
は例として使用されています。これはIDynamicMetaObjectProvider
を実装する任意のクラスです):
string key = "TestKey";
dynamic e = new ExpandoObject();
e[key] = "value";
これは次と同等です:
dynamic e = new ExpandoObject();
e.TestKey = "value";
または、前方反射の唯一の方法ですか?
それほど簡単ではありませんReflectionは、notdynamic
の全範囲である通常の型モデルを想定しているため、機能しません。実際に通常のオブジェクトと話しているだけの場合は、ここでリフレクションを使用してください。そうでなければ、コンパイラが基本的な割り当てのために出力するコードをリバースエンジニアリングし、柔軟にメンバー名を持つように微調整することを期待するかもしれません。正直言って、これは魅力的なオプションではありません。シンプルな:
dynamic foo = ...
foo.Bar = "abc";
に翻訳する:
if (<Main>o__SiteContainer0.<>p__Site1 == null)
{
<Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "Bar", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
}
<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, foo, "abc");
動的オブジェクトと非動的オブジェクトの両方で機能するアプローチが必要な場合: FastMember はこれに便利で、タイプまたはオブジェクトレベルで機能します。
// could be static or DLR
var wrapped = ObjectAccessor.Create(obj);
string propName = // something known only at runtime
Console.WriteLine(wrapped[propName]);
nugetで利用でき、動的および非動的シナリオの両方に最適化されています。
Paul Sasikは C#4.0 Dynamic vs Expando ...どこに収まりますか? で同様の質問に回答しました
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
var p = expando as IDictionary<String, object>;
p["A"] = "New val 1";
p["B"] = "New val 2";
Console.WriteLine(expando.A);
Console.WriteLine(expando.B);
}
}
Jonasの答えに追加するために、新しいvar pを作成する必要はありません。代わりにこのアプローチを使用してください。
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
((IDictionary<String, object>)expando)["A"] = "New val 1";
((IDictionary<String, object>)expando)["B"] = "New val 2";
Console.WriteLine(expando.A);
Console.WriteLine(expando.B);
}
}
私のオープンソースフレームワーク Dynamitey には、DLRを使用して文字列名に基づいて呼び出すためのメソッドがあります。バインディングサイトをキャッシュし、1つのメソッド呼び出しまで効率化します。また、非動的オブジェクトのリフレクションよりも高速に実行されます。
Dynamic.InvokeSet(e, "TestKey", "value");
fast-member は法案に合うかもしれません-その場でILを生成するように見えますが、最初の使用後に本当に高速になるようにそれをキャッシュします。