ValueInjector (NuGet の最新バージョン) を使用して、ビュー モデルに EntityFramework Code First オブジェクトのデータを挿入しようとしています。この逆もやりたいと思いますが、これは私が始めている試みです。
私はさまざまなマッピングを調査し、それらの多くを試しました。私が必要とするものを見つけることができず、私の必要性はかなり基本的なものだと思います(SOにはこれらの質問がいくつかあり、それぞれが異なる答えを得るようです.
私は本当にこれについてデューデリジェンスをしようとしました。CodePlex をググってトロールし、ProDinner アプリケーションをダウンロードしました (起動して実行し、デバッグでコードをステップ実行しました)。
私は、注入を処理する独自の ValueInjection クラスを持っているところです。コードとオブジェクトを非常にわかりやすい方法で貼り付けて、それらを取得して実行できるようにします。ベースの LoopValueInjection を使用するソリューションがありますが、エンティティからマッピングへのインジェクションとエンティティへのマッピングを手動で行う必要があるため、私はそれが好きではありません。ProDinner の例には、よりテンプレート化されたアプローチがあり、気に入っていましたが、自分のニーズに合わせることができませんでした。
私のコードが論理的に混乱しているのは、ソース プロパティの型が単純なオブジェクトでない場合に再帰的インジェクションを強制的に発生させる方法を理解していないことだと思います。この例では、Person.Address.* プロパティは、PersonViewModel クラスのプロパティと名前と型が一致します。ただし、インジェクションは Person のプロパティをループし、Person.Address プロパティの名前と型を照合しようとします。
ラインかと思った
Object result = Activator.CreateInstance(c.SourceProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);
この再帰を実行しますが、実行しないと思います。
だから...誰かがこれを修正する方法について私に指示を与えることができますか?
////// ENTITY MODELS
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
////// VIEW MODEL
public class PersonViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int PersonId { get; set; }
public int AddressId { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
////// CUSTOM INJECTOR
public class EntityToViewModel : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
//ignore int = 0 and DateTime = to 1/01/0001
if (c.SourceProp.Type == typeof(DateTime) && (DateTime)c.SourceProp.Value == default(DateTime) ||
(c.SourceProp.Type == typeof(int) && (int)c.SourceProp.Value == default(int)))
return false;
if (c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null)
return true;
if (c.SourceProp.Type == typeof(int) &&
c.TargetProp.Type == typeof(int) )
{
if( "id".Equals(c.SourceProp.Name.ToLower()) &&
c.TargetProp.Name.ToLower().EndsWith("id") &&
c.TargetProp.Name.StartsWith(c.Source.Type.Name))
return true;
}
//Transition logic to SetValue for value types. This should
//allow Address values on Person to be set.
if (!c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string)))
return true;
return false;
//put id logic matching here
//return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null;
}
protected override object SetValue(ConventionInfo c)
{
//If type is primative or string return the value as is
if (c.SourceProp.Type.IsPrimitive || c.SourceProp.Type.Equals(typeof(string)))
return c.SourceProp.Value;
Object result = Activator.CreateInstance(c.SourceProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);
//for simple object types create a new instace and apply the clone injection on it
return result;
}
}
////// Program.cs
public class Program
{
public static void Main(string[] args)
{
Person defaultPerson = getDefaultPerson();
//Throws an error. I'm not sure where in the pipeline this occurs, but
//it seems to happen somewhere other than the Match & SetValue method of
//my EntityToViewModel injection
PersonViewModel pvm = CreateFromEntity(defaultPerson);
//Works, but want it more generic & without having to
//include hardcoded prefix for every non-simple object on my EF Model
pvm = CreateFromEntityWorking(defaultPerson);
Console.ReadLine();
}
private static PersonViewModel CreateFromEntity(Person person)
{
PersonViewModel pvm = new PersonViewModel();
pvm.InjectFrom<EntityToViewModel>(person);
return pvm;
}
///WORKING MAPPING BUT SEEMS TOO HARDCODED
private static PersonViewModel CreateFromEntityWorking(Person person)
{
PersonViewModel personvm = new PersonViewModel();
//Fill out view model properties with the same name as those on Person
personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Person"), person);
if (person != null && person.Address != null)
{
//Fill out view model properties for the Address
personvm.InjectFrom(new LoopValueInjection().TargetPrefix("Address"), person.Address);
}
return personvm;
}
public static Person getDefaultPerson()
{
Person p = new Person();
Address a = new Address();
p.Id = 1;
p.FirstName = "John";
p.LastName = "McClain";
a.City = "New York";
a.State = "New York";
a.Zip = "55555";
a.Id = 2;
p.Address = a;
return p;
}
}