创建我自己的映射器
Creating my own mapper
这是我的情况。我有 2 个 classes,TmdbTvShow 和 TvShow。
TmdbTvShow class 充满了我从外部来源获得的数据。现在我想创建某种映射器将其映射到我自己的 class、TvShow.
Class 电视剧:
[MovieMap("TmdbTvShow")]
public class TvShow
{
public int ID { get; set; }
[MovieMapProperty("ID")]
public int TmdbID { get; set; }
[MovieMapProperty("Name")]
public string Name { get; set; }
[MovieMapProperty("OriginalName")]
public string OriginalName { get; set; }
[MovieMapProperty("Overview")]
public string Summary { get; set; }
[MovieMapProperty("FirstAirDate")]
public DateTime FirstAirDate { get; set; }
[MovieMapProperty("LastAirDate")]
public DateTime LastAirDate { get; set; }
[MovieMapProperty("Genres")]
public IEnumerable<Genre> Genres { get; set; }
[MovieMapProperty("InProduction")]
public bool Running { get; set; }
}
映射器class:
public class MovieMapper
{
public MovieMapper()
{
}
public T Map<T>(object input) where T : new()
{
T obj = new T();
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])obj.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
Dictionary<string, MovieMapPropertyAttribute> propAtts = new Dictionary<string, MovieMapPropertyAttribute>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
// Get value
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string))
{
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToBoolean(value), null);
}
else
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, value, null);
}
}
}
}
else
throw new Exception("Wrong object");
return obj;
}
}
所以 atm 我开始工作了,int、string、booleans 和 DateTime 之类的东西正在映射到我的对象。
但是如您所见,我的 TvShow class 中有一个 IEnumerable。这是此 TvShow 的流派合集。
我对如何使 2 个 IEnumerables 彼此映射有点困惑。
如果我像字符串那样做,我会收到此错误:
a object of type System.Collections.Generic.List can not be converted to the type System.Collections.Generic.IEnumerable
也许有人可以告诉我如何处理这个问题的正确方向?
干杯
您可以创建一个 IEnumerable
列表,向其中添加项目,然后将其分配给 属性。
如果您需要将对象从 TmdbGenre
转换为 Genre
,您可以递归调用 Map
,但您可能需要一个接受类型的 Map
版本范围。
public object Map(Type type, object input);
var result = value.Select(x => Map(prop.GetType().GetGenericArguments()[0], x));
prop.SetValue(obj, result);
好的,经过大量尝试我已经弄明白了。
这是我的解决方案:
public T Map<T>(object input) where T : new()
{
T obj = new T();
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])obj.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
Dictionary<string, MovieMapPropertyAttribute> propAtts = new Dictionary<string, MovieMapPropertyAttribute>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
if (input.GetType().GetProperty(mmp.PropertyName) != null)
{
// Get value
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string) && prop.PropertyType != typeof(string[]))
{
Type type = prop.PropertyType.GetGenericArguments()[0];
var list = (IEnumerable)value;
dynamic values = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
foreach (object ob in list)
{
object tempObj = Activator.CreateInstance(type);
tempObj = Map(ob, tempObj);
values.Add((dynamic)tempObj);
}
obj.GetType().GetProperty(prop.Name).SetValue(obj, values, null);
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToBoolean(value), null);
}
else if (typeof(int).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToInt32(value), null);
}
else if (typeof(float).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, float.Parse(value.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat), null);
}
else
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, value, null);
}
}
}
}
}
else
throw new Exception("Wrong object");
return obj;
}
private object Map(object input, object output)
{
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])output.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
foreach (PropertyInfo prop in output.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
if (input.GetType().GetProperty(mmp.PropertyName) != null)
{
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string) && prop.PropertyType != typeof(string[]))
{
Type type = prop.PropertyType.GetGenericArguments()[0];
var list = (IEnumerable)value;
dynamic values = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
foreach (object ob in list)
{
object tempObj = Activator.CreateInstance(type);
tempObj = Map(ob, tempObj);
values.Add((dynamic)tempObj);
}
output.GetType().GetProperty(prop.Name).SetValue(output, values, null);
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToBoolean(value), null);
}
else if (typeof(int).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToInt32(value), null);
}
else if (typeof(float).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, float.Parse(value.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat), null);
}
else
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, value, null);
}
}
}
}
}
else
throw new Exception("Wrong object");
return output;
}
它工作正常,它将 ienumerables 映射到 ienumerables 等中。
感谢 Ned 为我指明了正确的方向,我会把你作为一个好的答案!
这是我的情况。我有 2 个 classes,TmdbTvShow 和 TvShow。
TmdbTvShow class 充满了我从外部来源获得的数据。现在我想创建某种映射器将其映射到我自己的 class、TvShow.
Class 电视剧:
[MovieMap("TmdbTvShow")]
public class TvShow
{
public int ID { get; set; }
[MovieMapProperty("ID")]
public int TmdbID { get; set; }
[MovieMapProperty("Name")]
public string Name { get; set; }
[MovieMapProperty("OriginalName")]
public string OriginalName { get; set; }
[MovieMapProperty("Overview")]
public string Summary { get; set; }
[MovieMapProperty("FirstAirDate")]
public DateTime FirstAirDate { get; set; }
[MovieMapProperty("LastAirDate")]
public DateTime LastAirDate { get; set; }
[MovieMapProperty("Genres")]
public IEnumerable<Genre> Genres { get; set; }
[MovieMapProperty("InProduction")]
public bool Running { get; set; }
}
映射器class:
public class MovieMapper
{
public MovieMapper()
{
}
public T Map<T>(object input) where T : new()
{
T obj = new T();
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])obj.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
Dictionary<string, MovieMapPropertyAttribute> propAtts = new Dictionary<string, MovieMapPropertyAttribute>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
// Get value
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string))
{
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToBoolean(value), null);
}
else
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, value, null);
}
}
}
}
else
throw new Exception("Wrong object");
return obj;
}
}
所以 atm 我开始工作了,int、string、booleans 和 DateTime 之类的东西正在映射到我的对象。
但是如您所见,我的 TvShow class 中有一个 IEnumerable。这是此 TvShow 的流派合集。
我对如何使 2 个 IEnumerables 彼此映射有点困惑。 如果我像字符串那样做,我会收到此错误:
a object of type System.Collections.Generic.List can not be converted to the type System.Collections.Generic.IEnumerable
也许有人可以告诉我如何处理这个问题的正确方向?
干杯
您可以创建一个 IEnumerable
列表,向其中添加项目,然后将其分配给 属性。
如果您需要将对象从 TmdbGenre
转换为 Genre
,您可以递归调用 Map
,但您可能需要一个接受类型的 Map
版本范围。
public object Map(Type type, object input);
var result = value.Select(x => Map(prop.GetType().GetGenericArguments()[0], x));
prop.SetValue(obj, result);
好的,经过大量尝试我已经弄明白了。
这是我的解决方案:
public T Map<T>(object input) where T : new()
{
T obj = new T();
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])obj.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
Dictionary<string, MovieMapPropertyAttribute> propAtts = new Dictionary<string, MovieMapPropertyAttribute>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
if (input.GetType().GetProperty(mmp.PropertyName) != null)
{
// Get value
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string) && prop.PropertyType != typeof(string[]))
{
Type type = prop.PropertyType.GetGenericArguments()[0];
var list = (IEnumerable)value;
dynamic values = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
foreach (object ob in list)
{
object tempObj = Activator.CreateInstance(type);
tempObj = Map(ob, tempObj);
values.Add((dynamic)tempObj);
}
obj.GetType().GetProperty(prop.Name).SetValue(obj, values, null);
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToBoolean(value), null);
}
else if (typeof(int).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, Convert.ToInt32(value), null);
}
else if (typeof(float).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, float.Parse(value.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat), null);
}
else
{
// Set value to object
obj.GetType().GetProperty(prop.Name).SetValue(obj, value, null);
}
}
}
}
}
else
throw new Exception("Wrong object");
return obj;
}
private object Map(object input, object output)
{
MovieMapAttribute[] classAttributes = (MovieMapAttribute[])output.GetType().GetCustomAttributes(typeof(MovieMapAttribute), false);
if (classAttributes != null && classAttributes[0].ClassName.Equals(input.GetType().Name))
{
foreach (PropertyInfo prop in output.GetType().GetProperties())
{
MovieMapPropertyAttribute[] mma = (MovieMapPropertyAttribute[])prop.GetCustomAttributes(typeof(MovieMapPropertyAttribute), false);
// Attribute found
if (mma.Length > 0)
{
// Get attribute
MovieMapPropertyAttribute mmp = mma[0];
if (input.GetType().GetProperty(mmp.PropertyName) != null)
{
var value = input.GetType().GetProperty(mmp.PropertyName).GetValue(input, null);
// Is property a dateTime
if (typeof(DateTime).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToDateTime(value), null);
}
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string) && prop.PropertyType != typeof(string[]))
{
Type type = prop.PropertyType.GetGenericArguments()[0];
var list = (IEnumerable)value;
dynamic values = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
foreach (object ob in list)
{
object tempObj = Activator.CreateInstance(type);
tempObj = Map(ob, tempObj);
values.Add((dynamic)tempObj);
}
output.GetType().GetProperty(prop.Name).SetValue(output, values, null);
}
else if (typeof(Boolean).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToBoolean(value), null);
}
else if (typeof(int).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, Convert.ToInt32(value), null);
}
else if (typeof(float).IsAssignableFrom(prop.PropertyType))
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, float.Parse(value.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat), null);
}
else
{
// Set value to object
output.GetType().GetProperty(prop.Name).SetValue(output, value, null);
}
}
}
}
}
else
throw new Exception("Wrong object");
return output;
}
它工作正常,它将 ienumerables 映射到 ienumerables 等中。
感谢 Ned 为我指明了正确的方向,我会把你作为一个好的答案!