创建我自己的映射器

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 为我指明了正确的方向,我会把你作为一个好的答案!