インターフェイスを使用して、オブジェクトをあるタイプから別のタイプに変換しますか?
質問
同じインターフェイスを持つ2つのクラスがあるとします:
interface ISomeInterface
{
int foo{get; set;}
int bar{get; set;}
}
class SomeClass : ISomeInterface {}
class SomeOtherClass : ISomeInterface {}
SomeClassを表すISomeInterfaceのインスタンスがあるとします。各メンバーを手動でコピーせずに、それをSomeOtherClassの新しいインスタンスにコピーする簡単な方法はありますか?
更新:レコードについては、SomeClassのインスタンスをSomeOtherClassのインスタンスにキャストしようとはしません。私がやりたいのは次のようなものです:
ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();
soc.foo = sc.foo;
soc.bar = soc.bar;
これらのオブジェクトには多くのプロパティがあるため、それぞれを手動で行う必要はありません。
解決
"それを行う方法の例を教えていただけますか(または少なくとも、使用する適切な方法を教えてください)。 MSDNでそれらを見つけることができないようです" –ジェイソンベイカー
ジェイソン、次のようなもの:
var props = typeof(Foo)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props)
{
// p.Name gives name of property
}
実行時にリフレクティブに実行するのではなく、コピーコンストラクタに必要なコードを吐き出すツールを作成することをお勧めします-パフォーマンスが低下します。
他のヒント
各クラスで暗黙的な演算子を作成して、変換を行うことができます:
public class SomeClass
{
public static implicit operator SomeOtherClass(SomeClass sc)
{
//replace with whatever conversion logic is necessary
return new SomeOtherClass()
{
foo = sc.foo,
bar = sc.bar
}
}
public static implicit operator SomeClass(SomeOtherClass soc)
{
return new SomeClass()
{
foo = soc.foo,
bar = soc.bar
}
}
//rest of class here
}
そして SomeOtherClass soc = sc;
そしてその逆も機能します。
インターフェイスのポイントは、そうする必要がないということではありませんか? SomeOtherClassの具体的な実装で何かやっていますか?具体的な実装を使用する代わりに、インターフェイスを使用します。SomeClassまたはSomeOtherクラスを使用するかどうかは問題ではありません。
それ以外にできることは、次のようなインターフェイス上の各プロパティをコピーする何らかのヘルパー関数を記述することです(手動で行うか、リフレクションを調べる必要があります)。
public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
{
//copy properties here
return toSomeOtherClass;
}
しかし、私の最初の本能は、実装から遠ざかり、代わりにインターフェースを使用することに集中することです。そうすれば、何が下にあるかは関係ありません。
Reflection ...すべてのプロパティをループし、他のオブジェクトの対応するプロパティに設定します。
リフレクションソリューションに対するJoeの回答をご覧ください。
Visual Studioを使用していると仮定します。
ctrl + shift + rおよびctrl + shift + pのショートカットに慣れていますか? そうでない場合、ctrl + shift + rはキーストロークマクロの記録を開始/終了します。 ctrl + shift + pは、記録されたマクロを再生します。
多くのプロパティを設定したときに行ったのは、プロパティ宣言を設定したい場所にコピーし、宣言をsetステートメントに変更してカーソルを次の行に移動するためのマクロを記録することです、その後、すべてのsetステートメントが完了するまで再生します。
いいえ、オブジェクトをあるタイプから別のタイプに透過的に変換(キャスト)するには、オブジェクトの基礎となる具象クラスは、両方が同じ要素を使用している場合でも、キャストしようとしているクラスから継承する必要がありますインターフェース。
それについて考えてみましょう。同じインターフェースを実装するために、2つのオブジェクトすべてが共通して持つ必要があるのは、メソッドシグネチャの同じサブセットです。同じプロパティまたはデータフィールドさえ持っていない(おそらく持っていない)かもしれません。
これは機能しませんか?
class MyClass : ICloneable
{
public MyClass()
{
}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;
return mc;
}
MyClass.Clone()を呼び出すだけです。
ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();
foreach (PropertyInfo info in typeof(ISomeInterface)
.GetProperties(BindingFlags.Instance
|BindingFlags.Public))
{
info.SetValue(soc,info.GetValue(sc,null),null);
}
次のようにしましたが、暗黙の演算子を使用してあるオブジェクトから別のオブジェクトに変換するのに非常にうまく機能します:
class Program { static void Main(string[] args) { Console.WriteLine("hello"); ExecutionReport er = new ExecutionReport("ORDID1234",3000.43,DateTime.UtcNow); Order ord = new Order(); ord = er; Console.WriteLine("Transferred values are : " + er.OrderId + "\t" + ord.Amount.ToString() + "\t" + ord.TimeStamp.ToString() + "\t"); Console.ReadLine(); } } public class Order { public string OrderId { get; set; } public double Amount { get; set; } public DateTime TimeStamp { get; set; } public static implicit operator ExecutionReport(Order ord) { return new ExecutionReport() { OrderId = ord.OrderId, Amount = ord.Amount, TimeStamp = ord.TimeStamp }; } public static implicit operator Order(ExecutionReport er) { return new Order() { OrderId = er.OrderId, Amount = er.Amount, TimeStamp = er.TimeStamp }; } public Order() { } } public class ExecutionReport { public string OrderId { get; set; } public double Amount { get; set; } public DateTime TimeStamp { get; set; } public ExecutionReport() { } public ExecutionReport(string orderId,double amount, DateTime ts) { OrderId = orderId; Amount = amount; TimeStamp = ts; } }