LoginSignup
6
10

More than 5 years have passed since last update.

リフレクションを使ったクラス、構造体の値のコピー

Last updated at Posted at 2017-02-05

目的

クラス、構造体間で名前が一致しているものをコピーしたい。
いちいちコピーコンストラクタ等を書きたくないから。
速度等を気にする場合はしっかりと書くべきだけど
そうじゃないやつ向け

ソース

早速ソース。
基本的にはフィールドとプロパティを列挙して名前が一致したものに値を入れるだけ。
構造体の場合は値が反映されないので一旦ValueType において終わったら戻す必要あり。
実際には構造体とクラスで別々の関数にする必要あり。

※2017/2/7追記
@muro さんのご指摘の通り参照渡しですので使い方には注意を。
※2017/2/8追記
DeepCopyしたい場合は@muro さんのコメントを参考にしてください。


static public void CopyToData<T1, T2>(T1 source, T2 dest)
// where T2 : struct//これがないとValueType vt = dest;ができない。
{
    var destType = dest.GetType();
    var sourceType = source.GetType();
    //構造体の場合はValueTypeにいったん置き換えないと値が更新されない。
    //ValueType vt = dest;
    //構造体の場合は以下のdestをvtに置き換えが必要


  //お互いのフィールドとプロパティを列挙して名前が一致したものコピーする
    foreach (var destProperty in destType.GetProperties())
    {
        foreach (var sourceProprty in sourceType.GetProperties().Where(v => v.Name==destProperty.Name))
        {
            destProperty.SetValue(dest, sourceProprty.GetValue(source));
        }
        foreach (var sourceField in sourceType.GetFields().Where(v => v.Name==destProperty.Name))
        {
            destProperty.SetValue(dest, sourceField.GetValue(source));
        }
    }

    foreach (var destField in destType.GetFields())
    {
        foreach (var sourceProperty in sourceType.GetProperties().Where(v => v.Name==destField.Name))
        {
            destField.SetValue(dest, sourceProperty.GetValue(source));
        }
        foreach (var sourceField in sourceType.GetFields().Where(v => v.Name==destField.Name))
        {
            destField.SetValue(dest, sourceField.GetValue(source));
        }
   }

    //以下のはまた構造体のときに必要
    //構造体に戻す
    //dest = (T2)vt;
}

名前の一致しかとっていないので型が違うとダメになる
その場合は名前と一緒に「FieldType」も比較してあげるとよい

6
10
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10