私は現在、これに対して2つの異なるソリューションを持っています。1つはリフレクションを使用する場合と使用しない場合です。
1.)一般的な拡張メソッド(およびリフレクション)を使用すると、C#で次のように実行できます。
public static class Extension
{
public static T CreateCopy<T>(this T src)
where T: new()
{
if (src == null) return default(T); // just return null
T tgt = new T(); // create new instance
// then copy all properties
foreach (var pS in src.GetType().GetProperties())
{
foreach (var pT in tgt.GetType().GetProperties())
{
if (pT.Name != pS.Name) continue;
(pT.GetSetMethod()).Invoke(tgt, new object[] {
pS.GetGetMethod().Invoke(src, null) });
}
};
return tgt;
} // method
} // class
これは非常に強力です。これは、作成したクラスからのオブジェクトだけでなく、.NETFrameworkのシステムクラスを含むすべてのクラスからのオブジェクトだけでなく、すべてのオブジェクトのクローンを作成できるためです。そして、リフレクションのおかげで、そのプロパティを知る必要はありません。それらは自動的にコピーされます。
例
このメソッドを使用するにCreateCopy()
は、Customer
クラスとOrder
クラスがあり、コピー(参照ではなく)を作成する必要があるが、新しいIDを使用する必要があるとします。次に、次のことを実行できます。
Order CopyOrderWithNewPK(Order item)
{
Order newItem = item.CreateCopy(); // use ext. method to copy properties
newItem.OrderId = new Guid(); // create new primary key for the item
return newItem;
}
当然のことながら、Customerクラスの場合は同じように見えます。
Customer CopyCustomerWithNewPK(Customer item)
{
Customer newItem = item.CreateCopy(); // use ext. method to copy properties
newItem.CustomerId = new Guid(); // create new primary key for the item
return newItem;
}
サンプルクラス内で定義されたすべてのプロパティの値が自動的にコピーされることに注意してください。ソースコードを所有していない場合は、サードパーティアセンブリのオブジェクトのクローンを作成することもできます。トレードオフは、リフレクションアプローチが遅いことです。
2.)この質問に触発されて、反省なしでそれを行う別の方法があります。1つの利点は、Entity Frameworkのオブジェクトのクローンを作成できることです(たとえば、エンティティオブジェクトを別のデータコンテキストにアタッチおよび再アタッチするため)。
// using System.Runtime.Serialization;
public class Cloner<T>
{
readonly DataContractSerializer _serializer
= new DataContractSerializer(typeof(T));
/// <summary>
/// Clone an object graph
/// </summary>
/// <param name="graph"></param>
/// <returns></returns>
public T Clone(T graph)
{
MemoryStream stream = new MemoryStream();
_serializer.WriteObject(stream, graph);
stream.Seek(0, SeekOrigin.Begin);
return (T)_serializer.ReadObject(stream);
}
}
上記の例を壊さないために、CreateCopy
次のように拡張メソッドを変更できます。
public static class Extension
{
public static T CreateCopy<T>(this T src)
where T: new()
{
return (new Cloner<T>()).Clone(src);
}
}
注:Cloner
を使用していSystem.Runtime.Serialization
ますが、複製されるオブジェクトはシリアル化可能である必要はありません。これは利点になる可能性があります。私が見た他のソリューションでは、シリアル化可能なオブジェクトのみを複製できます。