Рамка за сливане на стопански субекти

Има ли някаква рамка, която може да направи следното:

var source = new Entity()
{
    StringProp = null,
    IntProp = 100,

};

var target = new Entity()
{
    StringProp = "stringValue", // Property value should remain the same if source value is null 
    IntProp = 222
};

var mergedEntity = MergeFramework.Merge(source, target); // Here is what I am looking for

Assert.AreEqual(100, mergedEntity.IntField);
Assert.AreEqual("stringValue", mergedEntity.StringField);

По-долу е работният процес, където имам нужда от него:

  1. Приложението получава екземпляр на обект. Някои свойства на екземпляра са нулеви. (изходен екземпляр)

  2. Приложението извлича от базата данни обекта със същата идентичност като в източника. (целеви екземпляр)

  3. Обединява два обекта и ги записва обединените в база данни.

Основният проблем е, че има близо 600 обекта в моя проект, така че не искам да пиша логика на сливане за всеки обект ръчно. По принцип търся нещо гъвкаво като AutoMapper или ValueInjecter, което да отговаря на следните изисквания:

  • Осигурете възможност за указване на условията за сливане на тип. Например: ако source.IntProp == int.MinInt -> не обединявайте свойството

  • Осигурете възможност за уточняване на специфични за имота условия. Като в AutoMapper:

    Mapper.CreateMap().ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date));


person k0stya    schedule 14.04.2012    source източник


Отговори (2)


Ето:

using System;
using NUnit.Framework;
using Omu.ValueInjecter;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var source = new Entity()
            {
                StringProp = null,
                IntProp = 100,

            };

            var target = new Entity()
            {
                StringProp = "stringValue", // Property value should remain the same if source value is null 
                IntProp = 222
            };

            var mergedEntity = (Entity) target.InjectFrom<Merge>(source);

            Assert.AreEqual(100, mergedEntity.IntProp);
            Assert.AreEqual("stringValue", mergedEntity.StringProp);
            Console.WriteLine("ok");
        }
    }

    public class Merge : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name
                   && c.SourceProp.Value != null;
        }
    }

    public class Entity
    {
        public string StringProp { get; set; }

        public int IntProp { get; set; }
    }

}
person Omu    schedule 15.04.2012

За да актуализирате текущия отговор, ConventionInjection е отхвърлен. Вече можете да използвате LoopInjection, когато създавате персонализирани инжекции.

Пример за актуализиран Merge клас на инжектиране:

public class Merge : LoopInjection
{

    protected override bool MatchTypes(Type source, Type target)
    {
        return source.Name == target.Name;
    }

    protected override void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
    {
        if (sp.GetValue(source) == null) return;
        base.SetValue(source, target, sp, tp);
    }

}
person Haukur Kristinsson    schedule 26.10.2016
comment
Сега използвам ExpressMapper вместо ValueInjector от сега нататък. :-) - person Haukur Kristinsson; 06.01.2017