对嵌套实体的反思

时间:2013-11-19 04:11:18

标签: c# reflection nested

我在名称空间GDeerParkEntity下有一个名为Buseartag的实体,下面是架构:

namespace GDeerParkEntity
{
    public class Buseartag
    {
        public Guid Eartag_id { get; set; }  //pk
        public String Eartag_code { get; set; }
        public Nullable<Guid> Sex_id { get; set; }
        public Nullable<Guid> Breed_id { get; set; }
        public Nullable<Guid> Primarily_id { get; set; }
        public Nullable<Guid> Bas_deerpen_id { get; set; }
        public String Chip_num { get; set; }
        public String Eartag_note { get; set; }
    }
}

我还在同一名称空间GDeerParkEntity下面有另一个名为Busremove的实体,其中包含Buseartag:

namespace GDeerParkEntity
{
    public class Busremove
    {
        public Guid Removeid { get; set; }                         
        public Nullable<Guid> Eartagid { get; set; }           
        public string Removereason { get; set; }                  
        public DateTime Removetime { get; set; }                
        public Guid Suppenid { get; set; }                      
        public Guid Subpenid { get; set; }                          
        public string Removenote { get; set; }                    

        public Buseartag BuseartagModel { get; set; }                      
     }
}

但是现在,在客户端,我有另外两个实体,其名称与上面相同,但名称空间不同。

 namespace ServiceProxy
 {
    public class Buseartag
    {
        public Guid Eartag_id { get; set; }  //pk
        public String Eartag_code { get; set; }
        public Nullable<Guid> Sex_id { get; set; }
        public Nullable<Guid> Breed_id { get; set; }
        public Nullable<Guid> Primarily_id { get; set; }
        public Nullable<Guid> Bas_deerpen_id { get; set; }
        public String Chip_num { get; set; }
        public String Eartag_note { get; set; }
    }
 }
===================================================
namespace ServiceProxy
{
    public class Busremove
    {
        public Guid Removeid { get; set; }                         
        public Nullable<Guid> Eartagid { get; set; }           
        public string Removereason { get; set; }                  
        public DateTime Removetime { get; set; }                
        public Guid Suppenid { get; set; }                      
        public Guid Subpenid { get; set; }                          
        public string Removenote { get; set; }                    

        public Buseartag BuseartagModel { get; set; }                      
     }
}

所以我想通过使用反射将GDeerParkEntity.Busremove实体转换为ServiceProxy.Busremove实体(因为有很多像这样的实体应该被转换,所以我使用T来覆盖这些场景):

 public  class Utils
{
    public static  T ConvertFromEntity<T, T1>(T1 t1) 
    {
        if (t1 == null) return default(T);

        Type type = typeof(T);
        Type typeEx = typeof(T1);

        PropertyInfo[] infoT = type.GetProperties();  
        PropertyInfo[] infoT1 = typeEx.GetProperties(); 

        T t= Activator.CreateInstance<T>();
        foreach (PropertyInfo pT in infoT)
        {
            string pTName = pT.Name;
            foreach (PropertyInfo pT1 in infoT1)
            {
                try
                {
                    if (pT1.Name.Equals(pTName))
                    {
                        if (!pT1.Name.ToLower().Contains("model"))
                        {
                            object pT1Value = pT1.GetValue(t1, null);
                            pT.SetValue(t as object, pT1Value, null);   
                            break;
                        }
                        else
                        {
                            //How should I do here to convert Buseartag?
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }
        return t;
    }

用法如下:

ServiceProxy.Busremove bus = Utils.ConvertFromEntity<ServiceProxy.Busremove, GDeerParkEntity.Busremove>(remove);

但是现在我在Busremove实体内转换Buseartag时有困难,任何人都可以帮助我吗?谢谢。 我尝试过type.getnestedtypes(),但它对我不起作用。

2 个答案:

答案 0 :(得分:1)

这样的东西有一个库 - AutoMapper。它被广泛使用,开源和经过充分测试。您可以使用NuGet安装它。 它用几行代码解决了你的问题:

using AutoMapper;

static class EntityConverter
{
    static EntityConverter()
    {
        AutoMapper.Mapper.CreateMap<GDeerParkEntity.Busremove, ServiceProxy.Busremove>();
        AutoMapper.Mapper.CreateMap<GDeerParkEntity.Buseartag, ServiceProxy.Buseartag>();
        AutoMapper.Mapper.CreateMap<ServiceProxy.Busremove, GDeerParkEntity.Busremove>();
        AutoMapper.Mapper.CreateMap<ServiceProxy.Buseartag, GDeerParkEntity.Buseartag>();
    }

    public static TDestination Convert<TSource, TDestination>(TSource source)
    {
        return AutoMapper.Mapper.Map<TSource, TDestination>(source);
    }
}

var sourceEntity = new GDeerParkEntity.Busremove()
var convertedEntity = EntityConverter.Convert<GDeerParkEntity.Busremove, ServiceProxy.Busremove>(sourceEntity);

如果您仍想重新发明轮子,可以保留类型映射的组合并检查属性值是否可以映射到其他类型:

static class EntityConverter
{
    private static Dictionary<Type, Type> _mappings =
        new Dictionary<Type, Type>()
        {
            { typeof(GDeerParkEntity.Busremove), typeof(ServiceProxy.Busremove) },
            { typeof(GDeerParkEntity.Buseartag), typeof(ServiceProxy.Buseartag) },
            { typeof(ServiceProxy.Busremove), typeof(GDeerParkEntity.Busremove) },
            { typeof(ServiceProxy.Buseartag), typeof(GDeerParkEntity.Buseartag) },
        };

    private static object ConvertEntity(object source, Type targetType)
    {
        var target = Activator.CreateInstance(targetType);
        TransferValues(source, target);
        return target;
    }

    private static void TransferValues(object source, object target)
    {
        var sourceProperties = source.GetType().GetProperties();
        var targetProperties = target.GetType().GetProperties();

        foreach(var srcProperty in sourceProperties)
        {
            var targetProperty = targetProperties.FirstOrDefault(p => p.Name == srcProperty.Name);
            if(targetProperty == null)
            {
                continue;
            }

            object value = srcProperty.GetValue(source);
            if(_mappings.ContainsKey(srcProperty.PropertyType))
            {
                value = ConvertEntity(value, _mappings[srcProperty.PropertyType]);
            }

            targetProperty.SetValue(target, value);
        }
    }

    public static TDestination ConvertEntity<TSource, TDestination>(TSource source)
    {
        var destination = Activator.CreateInstance<TDestination>();
        TransferValues(source, destination);
        return destination;
    }
}

用法与AutoMapper相同。

答案 1 :(得分:0)

嗯,我认为你需要的是这些实体的某种通用接口 然后你可以去..

if (pT1Value is IMyCommonEntityInterface)
{
... this bit is tricky ....
}

棘手的一点将涉及: -  1.根据命名约定,将子实体的名称转换为需要转换为的实体类型的名称。  2.按名称获取Type对象  3.对通用ConvertFromEntity方法进行递归调用,传递子实体类型和转换后的子实体类型,当然还有子项的值

C# call Generic method dynamically

这可能会帮助你。