克隆或将类及其子类属性注入另一个(从源到目标)

时间:2015-12-16 21:10:56

标签: c# .net valueinjecter

我正在努力从源到目标注入一个类及其子类属性。

例如,我从方法的返回值获取下面的对象。我需要将它注入目标类型。

Class A
{
  prop A
  prop B
}

Class B : A
{
  prop C
  prop D
}

我为数组和值检查编写了下面的代码,但是无法知道如何为类编写,即#34; IsClass"。没有互联网的地方我有一个想法,因为我的谷歌搜索说他们有IsGenericType。

请帮帮我

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

            if (c.SourceProp.Type.IsArray)
            {
                var arr = c.SourceProp.Value as Array;
                if (arr != null)
                {
                    var clone = Activator.CreateInstance(c.TargetProp.Type, arr.Length) as Array;

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

  **If c.SourceProp.Type.IsClass Then
                Return Activator.CreateInstance(c.SourceProp.Type).InjectFrom(Of CloneInjection)(c.SourceProp.Value)
            End If**

            return Activator.CreateInstance(c.TargetProp.Type)
                .InjectFrom<CloneInjection>(c.SourceProp.Value);
        }

更新

我添加了最后一个IsClass条件。仍然是我以前在没有添加它的情况下获得的相同例外。

  

类型&#39; System.MissingMemberException&#39;的例外情况发生在Microsoft.VisualBasic.dll中,但未在用户代码中处理。

     

其他信息:公共成员&#39; InjectFrom&#39;在类型&#39; B&#39;没找到。

1 个答案:

答案 0 :(得分:0)

Deevinee就像我在评论中所说的那样,我发布了一个解决方案,我为C#中的类似问题编写了一个解决方案。我希望它可以帮助你。

我决定编写一个静态方法来映射相同类型或不同类型但具有相同属性名称的两个实例的相应字段。

我现在试着动态调整代码,但没有测试能力,所以如果有一些编译错误,请原谅我。

    public static void Map (object objFrom, object objTo, StringComparison comparisionType = StringComparison.InvariantCulture)
    {
        if (objFrom != null && objTo != null)
        {
            PropertyInfo[] propTo = objTo.GetType().GetProperties( /*Optional binding flag to get private property use field instead to get each field not only properties*/ );

            foreach (PropertyInfo prop in objFrom.GetType().GetProperties( /*Optional binding flag to get private property use field instead to get each field not only properties*/) )
            {
                if ( !prop.CanRead )
                    continue;

                try
                {
                    object valFrom = objFrom.GetType().InvokeMember(prop.Name, BindingFlags.GetProperty /*as before play with binding flag here*/, null, objFrom, null);
                    PropertyInfo target = propTo.FirstOrDefault(x => x.Name.Equals(prop.Name, comparisionType));

                    if ( target == null || !target.CanWrite )
                        continue;

                    if (target.PropertyType.IsGenericType && target.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            if (prop.PropertyType.Equals(target.PropertyType))
                                objTo.GetType().InvokeMember(target.Name, BindingFlags.SetProperty, null, objTo, new object[1] { valFrom });
                        }
                        else
                        {
                            if (prop.PropertyType.Equals(Nullable.GetUnderlyingType(target.PropertyType)))
                                objTo.GetType().InvokeMember(target.Name, BindingFlags.SetProperty , null, objTo, new object[1] { valFrom });
                        }
                    }
                    else
                    {
                        if (prop.PropertyType.Equals(target.PropertyType))
                            objTo.GetType().InvokeMember(target.Name, BindingFlags.SetProperty, null, objTo, new object[1] { valFrom });
                    }
                }
                catch { }
            }
        }
    }

以下是有关绑定的一些信息: https://msdn.microsoft.com/it-it/library/kyaxdd3x(v=vs.110).aspx

如果你愿意在这个方法中应用一个函数(作为参数传递)来决定哪些属性需要相互映射,而不是依赖于名称相等(最大灵活性)。