【问题标题】:Creating my own mapper创建我自己的映射器
【发布时间】:2016-01-23 21:27:33
【问题描述】:

所以这是我的情况。我有 2 个课程,TmdbTvShow 和 TvShow。

TmdbTvShow 是一个填充了我从外部来源获得的数据的类。现在我想创建某种映射器来将其映射到我自己的类 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; }

}

映射器类:

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 课程中有一个 IEnumerable。这是此电视节目的流派集合。

我有点不知道如何使 2 个 IEnumerables 相互映射。 如果我像字符串一样执行此操作,则会收到此错误:

a object of type System.Collections.Generic.List can not be converted to the     type System.Collections.Generic.IEnumerable

也许有人可以让我在如何处理这个问题上朝着正确的方向前进?

干杯

【问题讨论】:

    标签: c# generics mapping ienumerable


    【解决方案1】:

    您可以创建一个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);
    

    【讨论】:

    • 我认为这行不通,因为我必须先映射 ienumerable 中的对象?它们必须从 TmdbGenre 映射到 Genre..
    【解决方案2】:

    好的,经过多次尝试,我想通了。

    这是我的解决方案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-13
      • 2011-09-05
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      相关资源
      最近更新 更多