سؤال

Is there any framework which can do the following:

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

Below is the workflow where I need it:

  1. App gets entity instance. Some properties of the instance are null. (source instance)

  2. App fetches from database the entity with the same identity as in the source. (target instance)

  3. Merges two entities and saves merged to database.

The main issue is that there are nearly 600 entities in my project, so I don't want to write merging logic for each entity manually. Basically, I am looking for something flexible like AutoMapper or ValueInjecter which satisfy the following requirements:

  • Provide possibility to specify type merge conditions. For example: if source.IntProp == int.MinInt -> do not merge the property

  • Provide possibility to specify property specific conditions. Like in AutoMapper:

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

هل كانت مفيدة؟

المحلول

here you go:

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

}

نصائح أخرى

To update the current answer, ConventionInjection has been deprecated. You can now use LoopInjection when creating custom injections.

Example of an updated Merge Injection class:

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

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