くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

コピー

C#で異なるオブジェクト間でプロパティの値をコピーするVer2

前書いたやつはプロパティしかコピーしてなかったのでフィールドもコピーするバージョン。

//使い方
//CopySameNameProperty(コピー元Object,コピー先Object)
public static void CopySameNameProperty(object from, object to)
{
    //それぞれのタイプを取得
    Type fromType = from.GetType();
    Type toType = to.GetType();
    //メンバーリスト
    MemberInfo[] fromMembers = fromType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    MemberInfo[] toMembers = toType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
    //名称用のリストを用意
    List<string> nameList = new List<string>();
    foreach (MemberInfo m in toMembers)
    {
        //プロパティとフィールドの場合のみ
        if (m.MemberType == MemberTypes.Property || m.MemberType == MemberTypes.Field)
        {
            nameList.Add(m.Name);
        }
    }

    //同名プロパティとフィールドの値をコピー
    foreach (MemberInfo m in fromMembers)
    {
        if (m.MemberType == MemberTypes.Property)
        {
            //同名のプパティがあれば転送する
            if (nameList.Contains(m.Name))
            {
                toType.GetProperty(m.Name).SetValue(to, fromType.GetProperty(m.Name).GetValue(from, null));
            }
        }
        else if(m.MemberType == MemberTypes.Field)
        {
            //同名のフィールドがあれば転送する
            if (nameList.Contains(m.Name))
            {
                toType.GetField(m.Name).SetValue(to, fromType.GetField(m.Name).GetValue(from));
            }
        }
    }
}

いちを、↓の感じくらいのオブジェクトだったら全部コピーしてくれる。

public class HogeClass
{
    //プロパティ
    public string s { get; set; }
    public string t { get; set; }
    public string r { get; set; }
    public List<int> list1 { get; set; }
    public FugaClass propertyclass { get; set; }
    //フィールド
    public string fieldstr = "";
    public List<int> list2 = new List<int>();
    public FugaClass fieldclass = new FugaClass();
}

C#で異なるオブジェクト間でプロパティの値をコピーする

どこかで、コードの大部分は値の代入で占められているという話を見た。 たしかに、単純転送みたいなものはかなり多い。.Net MVCで作ってると、とゆーかEntityFramework使ってると、ポコポコおぶじぇ祭りになりがち。View用に専用のモデルとか作ってると、テーブルのオブジェクトの値転送とか発狂しそうになる。

なので、2つのObjectで、同じ名前のプロパティの値をコピーするやつを作ってみた。割と便利。

//使い方
//CopySameNameProperty(コピー元Object,コピー先Object)
using System.Reflection;
public static void CopySameNameProperty(object from, object to)
{
	//それぞれのタイプを取得
	Type fromType = from.GetType();
	Type toType = to.GetType();
	//メンバーリスト
	MemberInfo[] fromMembers = fromType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
	MemberInfo[] toMembers = toType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
	//名称用のリストを用意
	List<string> nameList = new List<string>();
	foreach (MemberInfo m in toMembers)
	{
	    //プロパティの場合のみ
	    if (m.MemberType == MemberTypes.Property)
	    {
	        nameList.Add(m.Name);
	    }
	}

	//同名プロパティの値をコピー
	foreach (MemberInfo m in fromMembers)
	{
	    if (m.MemberType == MemberTypes.Property)
	    {
	        //同名のプパティがあれば転送する
	        if (nameList.Contains(m.Name))
	        {
	            toType.GetProperty(m.Name).SetValue(to, fromType.GetProperty(m.Name).GetValue(from, null));
	        }
	    }
	}
}

ただし、ってか当たり前だけど、データ型は合ってないと落ちる。あと、intとかstringあたり以外のオブジェクトだと参照渡しになって、コピー元の値を変えるとコピー先も変わるので一工夫必要かと。。。

ついでに、プロパティを初期化するやつも作ってみた。MVCで作ってると、 新規にモデル作るときに項目がNULLってくるので、初期化があると楽。他にもやり方はあるだろうけども。。。

using System.Reflection;
public static void NullValueInit(object targetObj)
{
	//Typeを取得
	Type targetType = targetObj.GetType();
	//メンバを取得する
	MemberInfo[] targetMembers = targetType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
	foreach (MemberInfo m in targetMembers)
	{
	    //プロパティの場合のみ
	    if (m.MemberType == MemberTypes.Property)
	    {
	        if (targetType.GetProperty(m.Name).GetValue(targetObj, null) == null)
	        {
	            //Int32の場合は0で初期化
	            if (targetType.GetProperty(m.Name).PropertyType.Name == "Int32")
	                targetType.GetProperty(m.Name).SetValue(targetObj, 0);
	            //Stringの場合は""で初期化
	            else if (targetType.GetProperty(m.Name).PropertyType.Name == "String")
	                targetType.GetProperty(m.Name).SetValue(targetObj, "");
	        }
	    }
	}
}

ちょっと改造版

問合せ