السيارات البسيطة للسيارات لرسم الخرائط في اتجاهين (كيانات/من ViewModels)

StackOverflow https://stackoverflow.com/questions/1781707

سؤال

تحديث: تطورت هذه الأشياء إلى مشروع جميل ، شاهدها في http://valueinjecter.codeplex.com


تحقق من ذلك ، لقد كتبت للتو سيارة بسيطة ، وتستغرق القيمة من الخاصية بنفس الاسم ونوع كائن واحد وتضعه في آخر ، ويمكنك إضافة استثناءات (IFS ، التبديل) لكل نوع قد تحتاجه

لذا قل لي ما رأيك في ذلك؟

لقد فعلت ذلك حتى أتمكن من فعل شيء مثل هذا:

Product –> ProductDTO

ProductDTO –> Product

هكذا بدأ:

أستخدم نوع "الكائن" في المدخلات/DTO/ViewModels للمنسدات لأنني أرسل إلى html a ienumerableu003CSelectListItem> وأتلقى مجموعة سلسلة من المفاتيح المحددة مرة أخرى

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

طريقة الخريطة الحقيقية

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;
        }
هل كانت مفيدة؟

المحلول

شيء واحد قد ترغب في إضافته هو تخزين بتات الانعكاس. إذا قمت بتخطيط كائن مرتين ، فربما لا ترغب في البحث عن جميع الأشياء المنعكسة مرة أخرى. أيضًا ، أشياء مثل GetValue و SetValue بطيئة جدًا ، لقد تحولت إلى المندوبين المتأخرين + Reflection.mit لتسريع الأمور.

نصائح أخرى

فقط استخدم السيارات. هذا جيد ، لكنه سوف ينمو ليصبح مشروعًا صغيرًا.

فقط بعض الأشياء (الحقيقية) هي:

  • الإبلاغ إذا كان لديك خصائص لا يمكن تعيينها
  • كائنات تسطيح
  • توفير السنانير لك لتخصيص بعض الجوانب ، وليس في بيان التبديل الكبير
  • باستخدام Expression.Compile لأسباب Perf بدلاً من التفكير مباشرة

لكن من المؤكد أنها مساحة مثيرة للاهتمام في الفوضى ، وفكرة رسم الخرائط التلقائية مفيدة بالتأكيد.

قليلا مثل دي في 15 أو 33 الخطوط مقابل Ninject أو أصدقائها - بارد ، ولكن لماذا؟.

أنا أعتبر أنك قرأت مقال وتعليقات بشأن رسم الخرائط على مدونة جيمي ?

مجرد فكرة:

قد يتساءل المرء عن الهدف من التجريد إذا تم تعيين التجريد بسهولة إلى تلك التي يتم استخلاصها.

يمكنك إضافة استثناءات (IFS ، التبديل) لكل نوع قد تحتاجه

أنت لن تفعل هذا. بجدية. عبارات الحالة التي تعمل على أنواع الكائنات هي نمط OOP سيء. أعني ، سيء حقًا. مثل القيادة مع مشروب من الفودكا داخل معدتك. قد ينجح الأمر لبعض الوقت ، ولكن في النهاية تواجه مشكلة.

حسنًا ، أخبرك جيمي بعدم استخدام السيارات ... لكنني أراهن أنه يعني شيئًا آخر. الآن ، هل اخترعت شيئًا مختلفًا - شيء يجعل جيمي سعيدًا؟ ؛-) لا ، لقد صنعت للتو سياراتك نصف مدفوعة. وأخبرك جيمي بعدم استخدامه! ؛-)

إذن هذا هو اقتراحي: تجاهل ما يقوله جيمي ، فقط فكر في نفسك .. واستخدم السيارات ؛-)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top