创建我自己的映射器



我的情况是这样的。我有两个类,TmdbTvShow和TvShow。

TmdbTvShow是一个充满数据的类,我已经从外部来源。现在我想创建某种映射器,将它映射到我自己的类TvShow。

类TvShow:

 [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; }
}

Mapper类:

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;
    }       
}

所以现在我让它工作了像int, string,布尔值&DateTime被映射到我的对象

但是你可以看到我有一个IEnumerable在我的TvShow类。这是一个流派的集合为这个电视节目。

我有点困于如何使两个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给我指出了正确的方向,我会把你作为一个好的答案!

最新更新