2

更新:このようなものは素晴らしいプロジェクトに進化しました。http: //valueinjecter.codeplex.comで参照してください。


これをチェックしてください。私は単純なオートマッパーを作成しました。これは、あるオブジェクトの同じ名前とタイプのプロパティから値を取得し、それを別のオブジェクトに配置します。必要なタイプごとに例外(ifs、switch)を追加できます。

それで、あなたはそれについてどう思いますか?

私はそれをしたので、私はこのようなことをすることができました:

Product –> ProductDTO

ProductDTO –> Product

それが始まった方法です:

DropDownsのInputs/Dto / ViewModelsで「object」タイプを使用します。これは、HTMLにIEnumerable <SelectListItem>を送信し、選択したキーの文字列配列を受け取るためです。

 public void Map(object a, object b)
    {
        var pp = a.GetType().GetProperties();
        foreach (var pa in pp)
        {
            var value = pa.GetValue(a, null);

            // property with the same name in b
            var pb = b.GetType().GetProperty(pa.Name);
            if (pb == null)
            {
                //no such property in b
                continue;
            }

            if (pa.PropertyType == pb.PropertyType)
            {
                pb.SetValue(b, value, null);
            }

        }
    }

更新: 実際の使用法:
ビルドメソッド(入力= Dto):

        public static TI BuildInput<TI, T>(this T entity) where TI: class, new()
        {
            var input = new TI();
            input = Map(entity, input) as TI;
            return input;
        }

        public static T BuildEntity<T, TI, TR>(this TI input)
            where T : class, new()
            where TR : IBaseAdvanceService<T>
        {               
            var id = (long)input.GetType().GetProperty("Id").GetValue(input, null);
            var entity = LocatorConfigurator.Resolve<TR>().Get(id) ?? new T();
            entity = Map(input, entity) as T;
            return entity;
        }

        public static TI RebuildInput<T, TI, TR>(this TI input)
            where T: class, new()
            where TR : IBaseAdvanceService<T>
            where TI : class, new()
        {

                return input.BuildEntity<T, TI, TR>().BuildInput<TI, T>();
            }

コントローラ内:

    public ActionResult Create()
    { 
        return View(new Organisation().BuildInput<OrganisationInput, Organisation>());
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(OrganisationInput o)
    {
        if (!ModelState.IsValid)
        {
            return View(o.RebuildInput<Organisation,OrganisationInput, IOrganisationService>());                
        }
        organisationService.SaveOrUpdate(o.BuildEntity<Organisation, OrganisationInput, IOrganisationService>());
        return RedirectToAction("Index");
    }

実際のMapメソッド

public static object Map(object a, object b)
        {
            var lookups = GetLookups();

            var propertyInfos = a.GetType().GetProperties();
            foreach (var pa in propertyInfos)
            {
                var value = pa.GetValue(a, null);

                // property with the same name in b
                var pb = b.GetType().GetProperty(pa.Name);
                if (pb == null)
                {
                    continue;
                }

                if (pa.PropertyType == pb.PropertyType)
                {
                    pb.SetValue(b, value, null);
                }
                else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(LookupItem))
                {
                    pb.SetValue(b, (pa.GetValue(a, null) as LookupItem).GetSelectList(pa.Name), null);
                }
                else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(object))
                {
                    pb.SetValue(b, pa.GetValue(a, null).ReadSelectItemValue(), null);
                }
                else if (pa.PropertyType == typeof(long) && pb.PropertyType == typeof(Organisation))
                {
                    pb.SetValue(b, pa.GetValue<long>(a).ReadOrganisationId(), null);
                }
                else if (pa.PropertyType == typeof(Organisation) && pb.PropertyType == typeof(long))
                {
                    pb.SetValue(b, pa.GetValue<Organisation>(a).Id, null);
                }
            }

            return b;
        }
4

4 に答える 4

6

AutoMapperを使用するだけです。これは問題ありませんが、ミニプロジェクトに成長します。

AM(本物)が行うことのほんの一部は次のとおりです。

  • マップできないプロパティがある場合のレポート
  • オブジェクトを平坦化する
  • 大きなswitchステートメントではなく、いくつかの側面をカスタマイズするためのフックを提供する
  • 直接反映するのではなく、パフォーマンス上の理由でExpression.Compileを使用する

しかし、それは確かに混乱するのに興味深いスペースであり、自動マッピングのアイデアは確かに役立ちます。

15行または33行のDIとNInjectまたはその友人との違いは少し似ていますが、なぜですか?

ジミーのブログの双方向マッピングに関する記事とコメントを読んだと思いますか?

于 2009-11-23T08:08:08.920 に答える
6

追加したいことの1つは、リフレクションビットをキャッシュすることです。オブジェクトを2回マップする場合、おそらくすべての反射要素を再度検索する必要はありません。また、GetValueやSetValueのようなものは非常に遅いので、速度を上げるためにレイトバウンドデリゲート+Reflection.Emitに切り替えました。

于 2009-11-23T13:36:37.837 に答える
3

ちょっとした考え:

抽象化が抽象化されているものに非常に簡単にマッピングされる場合、抽象化のポイントは何であるか疑問に思うかもしれません。

于 2009-11-23T08:30:06.043 に答える
3

必要になる可能性のあるタイプごとに例外(ifs、switch)を追加できます

あなたはこれをするつもりはありません。真剣に。オブジェクト型に作用するCaseステートメントは悪いOOPスタイルです。つまり、本当に悪いです。お腹の中にウォッカを飲みながら運転するようなものです。しばらくは動作するかもしれませんが、最終的には問題が発生します。

OKジミーは、AutoMapperを使用しないように言った...しかし、彼は別の意味を持っていたに違いない。さて、あなたは何か違うもの、つまりジミーを幸せにする何かを発明しましたか?;-)いいえ、あなたはあなた自身のハーフロールオートマッパーを作っただけです。そして、ジミーはあなたにそれを使わないように言いました!;-)

だからここに私の提案があります:ジミーの言うことを無視して、自分で考えてください..そしてAutoMapperを使用してください;-)

于 2009-11-23T09:58:39.770 に答える