次のシグネチャを持つメソッドを実装したい
_dynamic Cast(object obj, Type castTo);
_
誰もそれを行う方法を知っていますか? objはcastToを確実に実装しますが、アプリの実行時バインディングの一部を機能させるには、適切にキャストする必要があります。
編集:答えのいくつかが意味をなさない場合は、最初に誤ってdynamic Cast(dynamic obj, Type castTo);
と入力したためです-入力はobject
または他の保証された基本クラスでなければなりません
ここでキャストと変換の問題を混乱させていると思います。
どちらも同じC#演算子であるキャストを使用しているため、C#の2の違いを知るのは難しい場合がよくあります。
この状況では、ほぼ確実にキャスト操作を探していません。 dynamic
を別のdynamic
にキャストすることは、本質的にID変換です。同じ基になるオブジェクトへのdynamic
参照を取得しているだけなので、値は提供されません。結果のルックアップは同じです。
代わりに、このシナリオで必要と思われるのはコンバージョンです。それは、基になるオブジェクトを別の型にモーフィングし、dynamic
の方法で結果のオブジェクトにアクセスすることです。これに最適なAPIはConvert.ChangeType
。
public static dynamic Convert(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}
[〜#〜] edit [〜#〜]
更新された質問には次の行があります。
objはcastToを確実に実装します
この場合、Cast
メソッドは存在する必要はありません。ソースobject
は、単にdynamic
参照に割り当てることができます。
dynamic d = source;
達成しようとしているのは、source
参照を介してdynamic
の階層にある特定のインターフェイスまたはタイプを確認することです。それは単に不可能です。結果のdynamic
参照は、実装オブジェクトを直接参照します。ソースの階層内の特定のタイプを調べません。したがって、階層内の別の型にキャストしてからdynamic
に戻すという考え方は、最初にdynamic
に割り当てるだけとまったく同じです。引き続き同じ基礎オブジェクトを指します。
これは動作するはずです:
public static dynamic Cast(dynamic obj, Type castTo)
{
return Convert.ChangeType(obj, castTo);
}
編集
次のテストコードを作成しました。
var x = "123";
var y = Cast(x, typeof(int));
var z = y + 7;
var w = Cast(z, typeof(string)); // w == "130"
PHP、JavaScript、またはPython(converts目的の型の値)。それが良いことかどうかはわかりませんが、確かに機能します... :-)
私がこれまでに得たベスト:
dynamic DynamicCast(object entity, Type to)
{
var openCast = this.GetType().GetMethod("Cast", BindingFlags.Static | BindingFlags.NonPublic);
var closeCast = openCast.MakeGenericMethod(to);
return closeCast.Invoke(entity, new[] { entity });
}
static T Cast<T>(object entity) where T : class
{
return entity as T;
}
私はこれに答えられたことに気付きましたが、別のアプローチを使用し、共有する価値があると考えました。また、私のアプローチでは、不要なオーバーヘッドが生じる可能性があると感じています。しかし、私たちが観察している負荷の下でそれが悪いことを観察したり、計算したりすることはできません。このアプローチに関する有用なフィードバックを探していました。
ダイナミクスを使用する際の問題は、ダイナミックオブジェクトに関数を直接アタッチできないことです。毎回把握したくない割り当てを把握できるものを使用する必要があります。
この単純なソリューションを計画するとき、類似のオブジェクトを再入力しようとするときに有効な仲介者とは何かを見ました。バイナリ配列、文字列(xml、json)、または変換のハードコーディング( IConvertable )が通常のアプローチであることがわかりました。コードの保守性と遅延のために、バイナリ変換を行いたくありません。
私の理論では、 Newtonsoft は文字列仲介を使用してこれを行うことができました。
欠点として、文字列をオブジェクトに変換するときに、一致するプロパティを持つオブジェクトの現在のアセンブリを検索することでリフレクションを使用し、タイプを作成してからプロパティをインスタンス化することはかなり確信しています。 trueの場合、これらすべてを回避可能なオーバーヘッドと見なすことができます。
C#:
//This lives in a helper class
public static ConvertDynamic<T>(dynamic data)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(data));
}
//Same helper, but in an extension class (public static class),
//but could be in a base class also.
public static ToModelList<T>(this List<dynamic> list)
{
List<T> retList = new List<T>();
foreach(dynamic d in list)
{
retList.Add(ConvertDynamic<T>(d));
}
}
そうは言っても、これは私がまとめた別のユーティリティに適合し、任意のオブジェクトをダイナミックにすることができます。私はそれを正しく行うために反射を使用しなければならなかったことを知っています:
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return expando as ExpandoObject;
}
私はその機能を提供しなければなりませんでした。動的型付き変数に割り当てられた任意のオブジェクトはIDictionaryに変換できず、ConvertDynamic関数が破損します。この関数チェーンを使用するには、System.Dynamic.ExpandoObjectまたはIDictionary <string、object>のダイナミクスを提供する必要があります。
ジェネリックを試してください:
public static T CastTo<T>(this dynamic obj, bool safeCast) where T:class
{
try
{
return (T)obj;
}
catch
{
if(safeCast) return null;
else throw;
}
}
これは拡張メソッド形式であるため、その使用法は動的オブジェクトのメンバーであるかのようになります。
dynamic myDynamic = new Something();
var typedObject = myDynamic.CastTo<Something>(false);
編集:Grr、それを見ませんでした。はい、反射的にジェネリックを閉じることができ、非ジェネリック拡張メソッドで隠すことは難しくありません:
public static dynamic DynamicCastTo(this dynamic obj, Type castTo, bool safeCast)
{
MethodInfo castMethod = this.GetType().GetMethod("CastTo").MakeGenericMethod(castTo);
return castMethod.Invoke(null, new object[] { obj, safeCast });
}
私はあなたがこれから何を得るのか分からないだけです。基本的には、ダイナミックを使用し、キャストをリフレクトされた型に強制し、それをダイナミックに戻します。たぶんあなたは正しい、私は尋ねるべきではありません。しかし、これはおそらくあなたが望むことをするでしょう。基本的にダイナミックランドに入ると、リフレクティブメソッドまたは試行錯誤によってオブジェクトが何であるかを発見できるため、ほとんどのキャスト操作を実行する必要がなくなります。そのため、エレガントな方法はあまりありません。