どこかで、コードの大部分は値の代入で占められているという話を見た。 たしかに、単純転送みたいなものはかなり多い。.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, "");
	        }
	    }
	}
}

ちょっと改造版