Reputation: 916
I have an Entity named Buseartag under namespace GDeerParkEntity, below is the schema:
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; }
}
}
I also have another Entity named Busremove with Buseartag inside under the same namespace GDeerParkEntity:
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; }
}
}
But now, in the client, I have another two entitys with the same names as above but namespace different.
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; }
}
}
So I want to convert the GDeerParkEntity.Busremove entity to ServiceProxy.Busremove entity by using reflection (because there are a lot of entities like this should be converted, So I used T to cover these scenario):
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;
}
The usage is like below:
ServiceProxy.Busremove bus = Utils.ConvertFromEntity<ServiceProxy.Busremove, GDeerParkEntity.Busremove>(remove);
But now I have diffcult in converting Buseartag inside Busremove entity, anyone can help me ? thx. I have tried type.getnestedtypes() but it didn't work for me.
Upvotes: 1
Views: 287
Reputation: 6864
Well I think what you need is some sort of common interface for these entities Then you could go..
if (pT1Value is IMyCommonEntityInterface)
{
... this bit is tricky ....
}
The tricky bit will involve:- 1. Based on naming conventions convert the name of the child entity to the name of the type of the entity it need to be converted to. 2. Get the Type object by its name 3. Make a recursive call to your generic ConvertFromEntity method passing the child entity type and the converted child entity type and of course the value of the child
C# call Generic method dynamically
This might help you out.
Upvotes: 0
Reputation: 34417
There is a library for such stuff - AutoMapper. It is widely used, open-source and well tested. You can install it using NuGet. It solves you problem with several lines of code:
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);
If you still want to reinvent the wheel, you can keep a coolection of type mappings and check if property value can be mapped to some other type:
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;
}
}
Usage is the same as with AutoMapper.
Upvotes: 1