首页 > 解决方案 > 如何检查类型是否为自定义类

问题描述

我正在尝试使用以下方法从数据表中填充对象列表

public static List<T> toList<T>(this DataTable table) where T : new()
{
    try
    {
        List<T> list = new List<T>();

        foreach (var row in table.AsEnumerable())
        {
            var obj = new T();
            foreach (var prop in typeof(T).GetProperties())
            {
                PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                Type targetType = propertyInfo.PropertyType;
                if (table.Columns.Contains(prop.Name))
                {
                    try
                    {
                        object value = row[prop.Name];
                        if (value != null)
                        {
                            if (value.GetType() == typeof(string))
                            {
                                if (string.IsNullOrWhiteSpace(value.ToString()))
                                {
                                    value = null;
                                }
                            }
                            if (targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
                            {
                                targetType = Nullable.GetUnderlyingType(targetType);
                            }

                            value = Convert.ChangeType(value, targetType);
                            propertyInfo.SetValue(obj, value);
                        }
                    }
                    catch
                    {
                        continue;
                    }
                }
            }

            list.Add(obj);
        }

        return list;
    }
    catch (Exception ex)
    {
        return null;
    }
}

我有以下型号

public class A
{
    public string str1 {get;set;}
    public int int1 {get;set;}
    public DateTime dateTime1 {get;set;}
}
public class B
{
    public string str2 {get;set;}
    public int int2 {get;set;}
    public DateTime dateTime2 {get;set;}
    public A vara {get;set;}
}

我的数据表看起来像这样

+-----------+-----------+-----------+-----------+---------------+---------------+
|   str1    |   str2    |   int1    |   int2    |   dateTime1   |   dateTime2   |
+-----------+-----------+-----------+-----------+---------------+---------------+
|   "abc"   |   "def"   |   1       |   2       |   NULL        |   NULL        |
+-----------+-----------+-----------+-----------+---------------+---------------+

这一切都很好如果我使用

List<B> list = dataTable.toList<B>();

但我也想在列表的每个元素中设置 vara 的值。

如何检查类型是否是自定义类型? 我不能使用 Type.IsClass 因为它也适用于字符串。如果我可以检测到某个属性是自定义类类型,那么我可以使用相同的方法填充该值。我希望我已经解释清楚了。

标签: c#

解决方案


我能够创建以下通用解决方案

public static List<T> toList<T>(this DataTable table) where T : new()
{
    try
    {
        var list = table.toList(typeof(T));
        var newLIst = list.Cast<T>().ToList();
        return newLIst;
    }
    catch 
    {
        return null;
    }
}

public static List<object> toList(this DataTable table, Type type)
{
    try
    {
        List<object> list = new List<object>();
        foreach (var row in table.AsEnumerable())
        {
            var obj = row.toObject(type);
            list.Add(obj);
        }
        return list;
    }
    catch 
    {
        return null;
    }
}

public static object toObject(this DataRow row, Type type, string sourcePropName = "")
{
    try
    {
        var obj = Activator.CreateInstance(type);
        var props = type.GetProperties();
        foreach (var prop in props)
        {
            PropertyInfo propertyInfo = type.GetProperty(prop.Name);
            Type targetType = propertyInfo.PropertyType;
            string propName = prop.Name;
            if (!string.IsNullOrWhiteSpace(sourcePropName))
            {
                propName = sourcePropName + "__" + propName;
                if (!row.Table.Columns.Contains(propName))
                {
                    propName = prop.Name;
                }
            }
            if (row.Table.Columns.Contains(propName))
            {
                try
                {
                    object value = row[propName];
                    if (value != null)
                    {
                        if (value.GetType() == typeof(string))
                        {
                            if (string.IsNullOrWhiteSpace(value.ToString()))
                            {
                                value = null;
                            }
                        }
                        targetType = targetType.handleNullableType();
                        value = Convert.ChangeType(value, targetType);
                        propertyInfo.SetValue(obj, value);
                    }
                }
                catch
                {
                    continue;
                }
            }
            else
            if (targetType.IsClass && targetType != typeof(string))
            {
                if (targetType.IsGenericList())
                {
                    Type ltype = targetType.GetProperty("Item").PropertyType;
                    object value = row.toObject(ltype, propName);
                    if (value == null)
                    {
                        continue;
                    }
                    var valList = new List<object> { value }.ConvertList(targetType);
                    try
                    {
                        propertyInfo.SetValue(obj, valList);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                    }
                }
                else
                {
                    object value = row.toObject(targetType, propName);
                    propertyInfo.SetValue(obj, value);
                }
            }
        }
        return obj;
    }
    catch 
    {
        return null;
    }
}

public static object ConvertList(this List<object> value, Type type)
{
    IList list = (IList)Activator.CreateInstance(type);
    foreach (var item in value)
    {
        list.Add(item);
    }
    return list;
}

为了填充 B 类的所有属性,包括 vara 属性,我必须为属于 vara 属性的列的名称添加前缀并添加拆分器___

因此,关于表应该如下

+-----------------+-----------+-----------------+-----------+---------------------+---------------+
|   vara__str1    |   str2    |   vara__int1    |   int2    |   vara__dateTime1   |   dateTime2   |
+-----------------+-----------+-----------------+-----------+---------------------+---------------+
|   "abc"         |   "def"   |   1             |   2       |   NULL              |   NULL        |
+-----------------+-----------+-----------------+-----------+---------------------+---------------+

推荐阅读