2

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;
    }   

}
4

1 に答える 1

2

最後に、必要な例を見つけました。悲しいことに、私のすべての検索にもかかわらず、私はたった今これらに着陸した. それは私のせいではありません。しかし、蹴りすぎて足が痛い。

関連 URL:

ドキュメント (RTFM) http://valueinjecter.codeplex.com/documentation

フラット化の例と規則 http://valueinjecter.codeplex.com/wikipage?title=flattening&referringTitle=Documentation

非平坦化の例と規則 http://valueinjecter.codeplex.com/wikipage?title=unflattening&referringTitle=Documentation

私の問題の解決策:

ビュー モデルで使用する必要がある規則は、最上位のプロパティには、エンティティに存在するようなプロパティ名のプレフィックスを付けないことです。そのため、FirstName、LastName、および Id がすべて Person エンティティの最上位プロパティとして存在する以下のクラスでは、ビュー モデル クラスでプレフィックスが付けられません。Person.Address プロパティの City、State、Zip、および Id にはプレフィックスが付きます。

奇妙なことに、私は自分のインジェクションを実装しようとしているときにこの解決策を考えました。Entity から ViewModel に移行する作業が 1 つ得られました....その逆ではありません。

public class PersonViewModelPrefixed
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Id { get; set; }
    public int AddressId { get; set; }
    public string AddressCity { get; set; }
    public string AddressState { get; set; }
    public string AddressZip { get; set; } 
}

public static void Main(string[] args)
{   
        Person defaultPerson = getDefaultPerson();
        PersonViewModelPrefixed defaultPrefixedVm = getDefaultPrefixedViewModel();

        //flatten - Entity to View Model
        PersonViewModelPrefixed pvm = Flatten(defaultPerson);

        //unflatten - View Model to Entity
        Person person2 = Unflatten(defaultPrefixedVm);  
    Console.ReadLine();
}       

//unflatten - View Model to Entity
private static Person Unflatten(PersonViewModelPrefixed personViewModel)
{
    Person p = new Person();
    p.InjectFrom<UnflatLoopValueInjection>(personViewModel);
    return p;
}

//flatten - Entity to View Model
private static PersonViewModelPrefixed Flatten(Person person)
{
    PersonViewModelPrefixed pvm = new PersonViewModelPrefixed();
    pvm.InjectFrom<FlatLoopValueInjection>(person);
    return pvm;
}

したがって、これらの詳細を考えると、 Flatten および Unflatten メソッドをより一般的にする方法について何か提案はありますか? それが私が次に取り組むことです。

于 2012-10-11T14:29:15.920 に答える