[C#]ValueInjecter之三

  • 386
  • 0
  • C#
  • 2016-12-30

自訂義Injection 與 ValueInjecter Clone使用說明

InjectFrom 其中有一個泛型的應用, InjectFrom<T>,意思是,可自定義Injection的規則

只要新增一個class,並且繼承LoopInjection,就可以自訂義Injection規則,請看以下取自官方網站的範例

public class CloneInjection : LoopInjection
{
    protected override void Execute(PropertyInfo sp, object source, object target)
    {
        var tp = target.GetType().GetProperty(sp.Name);
        if (tp == null) return;
        var val = sp.GetValue(source);
        if (val == null) return;

        tp.SetValue(target, GetClone(sp, val));
    }

    private static object GetClone(PropertyInfo sp, object val)
    {
        if (sp.PropertyType.IsValueType || sp.PropertyType == typeof(string))
        {
            return val;
        }

        if (sp.PropertyType.IsArray)
        {
            var arr = val as Array;
            var arrClone = 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;

                arrClone.SetValue(Activator.CreateInstance(a.GetType()).InjectFrom<CloneInjection>(a), index);
            }

            return arrClone;
        }

        if (sp.PropertyType.IsGenericType)
        {
            //handle IEnumerable<> also ICollection<> IList<> List<>
            if (sp.PropertyType.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
            {
                var genericType = sp.PropertyType.GetGenericArguments()[0];

                var listType = typeof(List<>).MakeGenericType(genericType);
                var list = Activator.CreateInstance(listType);

                var addMethod = listType.GetMethod("Add");
                foreach (var o in val as IEnumerable)
                {
                    var listItem = genericType.IsValueType || genericType == typeof(string) ? o : Activator.CreateInstance(genericType).InjectFrom<CloneInjection>(o);
                    addMethod.Invoke(list, new[] { listItem });
                }

                return list;
            }

            //unhandled generic type, you could also return null or throw
            return val;
        }

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

此Injection是可複製一個類別的功能,使用起來非常簡單

var customer = new Customer()
{
    Id = 1,
    FirstName = "Clone",
    LastName = "Miles",
    Tel = "0978123456",
    ZipCode = "476",
    Address = "台北市信義區"
};

var clone = new Customer().InjectFrom<CloneInjection>(customer) as Customer;

Console.WriteLine(clone.Id);

另外官方還有很多預設寫好的Injection,IntToEnum、DateTimeToStr...等等

參考資料:https://github.com/omuleanu/ValueInjecter

 

 

一天一分享,身體好健康。

該追究的不是過去的原因,而是現在的目的。