ValueInjecter Как мне обновить код с V2.4 до V3.2, без внедрения соглашения - PullRequest
1 голос
/ 18 апреля 2020

Я работаю над обновлением приложения с net framework до. net core 3.0. Я использую windows Presentation Foundation Wpf, и я хочу реализовать ValueInjecter в его последней версии 3.2 ... Приложение в настоящее время работает на версии 2.4 помощи ValueInjecter, пожалуйста! В Интернете не так много документации. Как будет выглядеть этот код? Мой CloneInjection.cs:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Omu.ValueInjecter;

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

        protected override object SetValue(ConventionInfo c)
        {
            //for value types and string just return the value as is
            if (c.SourceProp.Type.IsValueType || c.SourceProp.Type == typeof(string))
                return c.SourceProp.Value;

            //handle arrays
            if (c.SourceProp.Type.IsArray)
            {
                var arr = c.SourceProp.Value as Array;
                var clone = arr.Clone() as Array;

                for (int index = 0; index < arr.Length; index++)
                {
                    var a = arr.GetValue(index);
                    if (a.GetType().IsValueType || a is string) continue;
                    clone.SetValue(Activator.CreateInstance(a.GetType()).InjectFrom<CloneInjection>(a), index);
                }
                return clone;
            }


            if (c.SourceProp.Type.IsGenericType)
            {
                //handle IEnumerable<> also ICollection<> IList<> List<>
                if (c.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
                {
                    var t = c.SourceProp.Type.GetGenericArguments()[0];
                    if (t.IsValueType || t == typeof(string)) return c.SourceProp.Value;

                    var tlist = typeof(List<>).MakeGenericType(t);
                    var list = Activator.CreateInstance(tlist);

                    var addMethod = tlist.GetMethod("Add");
                    foreach (var o in c.SourceProp.Value as IEnumerable)
                    {
                        var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
                        addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
                    }
                    return list;
                }

                //unhandled generic type, you could also return null or throw
                return c.SourceProp.Value;
            }

            //for simple object types create a new instace and apply the clone injection on it
            return Activator.CreateInstance(c.SourceProp.Type)
                .InjectFrom<CloneInjection>(c.SourceProp.Value);
        }
    }
}

Мой EntityInjection.cs:

using System.Collections;
using System.Diagnostics;
using System.Linq;
using Omu.ValueInjecter;

namespace Infrastructure.Data.Injection
{
    public class EntityInjection : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            var propertyMatch = c.SourceProp.Name == c.TargetProp.Name;
            var sourceNotNull = c.SourceProp.Value != null;

            bool targetPropertyIdWritable = !(propertyMatch && c.TargetProp.Name == "Id" && !(c.Target.Value is IEntityClass));

            return propertyMatch && sourceNotNull && targetPropertyIdWritable;
        }

        protected override object SetValue(ConventionInfo c)
        {
            if (c.SourceProp.Type.IsValueType || c.SourceProp.Type == typeof(string))
                return c.SourceProp.Value;

            if (c.SourceProp.Type.IsGenericType)
            {
                var td = c.SourceProp.Type.GetGenericTypeDefinition();
                if (td != null && td.GetInterfaces().Contains(typeof(IEnumerable)))
                {
                    var targetChildType = c.TargetProp.Type.GetGenericArguments()[0];
                    if (targetChildType.IsValueType || targetChildType == typeof(string)) return c.SourceProp.Value;
                    if (targetChildType.GetInterfaces().Any(x => x == typeof(IValueClass)))
                    {
                        var deleteMethod = c.TargetProp.Value.GetType().GetMethod("Remove");
                        var rmvItems = (c.TargetProp.Value as IEnumerable).Cast<IValueClass>()
                            .Where(x => x.Id > 0 && !(c.SourceProp.Value as IEnumerable).Cast<IValueClass>().Any(y => y.Id == x.Id));
                        rmvItems.ToList().ForEach(x => deleteMethod.Invoke(c.TargetProp.Value, new[] { x }));
                        rmvItems = (c.TargetProp.Value as IEnumerable).Cast<IValueClass>()
                            .Where(x => !(c.SourceProp.Value as IEnumerable).Cast<IValueClass>().Contains(x));
                        rmvItems.ToList().ForEach(x => deleteMethod.Invoke(c.TargetProp.Value, new[] { x }));

                        var sourceCollection = (c.SourceProp.Value as IEnumerable).Cast<IValueClass>();

                        foreach (var s in sourceCollection)
                        {
                            var sv = s;

                            var target = (c.TargetProp.Value as IEnumerable).Cast<IValueClass>().SingleOrDefault(z => z.Id == sv.Id && z.Id != 0);
                            if (target != null) target.InjectFrom<EntityInjection>(sv);
                            else if (!(c.TargetProp.Value as IEnumerable).Cast<IValueClass>().Contains(sv))
                            {
                                if (!(sv is IEntityClass))
                                {
                                    sv = Activator.CreateInstance(targetChildType) as IValueClass;
                                    Debug.Assert(sv != null);
                                    sv.InjectFrom<EntityInjection>(s);
                                    sv.Id = 0;
                                }

                                var addMethod = c.TargetProp.Value.GetType().GetMethod("Add");
                                addMethod.Invoke(c.TargetProp.Value, new[] { sv });
                            }
                        }
                    }
                }

                return c.TargetProp.Value;
            }

            if (c.SourceProp.Value is IEntityClass)
            {
                return c.SourceProp.Value;
            }

            if (c.TargetProp.Value == null)
            {
                try
                {
                    c.TargetProp.Value = Activator.CreateInstance(c.TargetProp.Type);
                }
                catch (Exception)
                {
                    return null;
                }
            }

            return c.TargetProp.Value.InjectFrom<EntityInjection>(c.SourceProp.Value);
        }
    }
}

1 Ответ

1 голос
/ 18 апреля 2020

если вы не можете переключиться на LoopInjection, вы также можете попробовать добавить этот класс в ваш проект:

public abstract class ConventionInjection : ValueInjection
{
    protected abstract bool Match(ConventionInfo c);

    protected virtual object SetValue(ConventionInfo c)
    {
        return c.SourceProp.Value;
    }

    protected override void Inject(object source, object target)
    {
        var sourceProps = source.GetProps();
        var targetProps = target.GetProps();

        var ci = new ConventionInfo
                     {
                         Source =
                             {
                                 Type = source.GetType(), 
                                 Value = source
                             },
                         Target =
                             {
                                 Type = target.GetType(),
                                 Value = target
                             }
                     };

        for (var i = 0; i < sourceProps.Count; i++)
        {
            var s = sourceProps[i];
            ci.SourceProp.Name = s.Name;
            ci.SourceProp.Value = s.GetValue(source);
            ci.SourceProp.Type = s.PropertyType;

            for(var j=0; j < targetProps.Count; j++)
            {
                var t = targetProps[j];
                ci.TargetProp.Name = t.Name;
                ci.TargetProp.Value = t.GetValue(target);
                ci.TargetProp.Type = t.PropertyType;
                if (Match(ci))
                    t.SetValue(target, SetValue(ci));
            }
        }
    }
}

public class ConventionInfo
{
    public ConventionInfo()
    {
        Source = new TypeInfo();
        Target = new TypeInfo();
        SourceProp = new PropInfo();
        TargetProp = new PropInfo();
    }

    public TypeInfo Source { get; set; }
    public TypeInfo Target { get; set; }

    public PropInfo SourceProp { get; set; }
    public PropInfo TargetProp { get; set; }

    public class PropInfo
    {
        public string Name { get; set; }
        public Type Type { get; set; }
        public object Value { get; set; }
    }

    public class TypeInfo
    {
        public Type Type { get; set; }
        public object Value { get; set; }
    }
}
...