【问题标题】:Mapping Composite Object using Reflection and ValueInjecter使用 Reflection 和 ValueInjecter 映射复合对象
【发布时间】:2011-10-27 08:41:03
【问题描述】:

也许这个问题,一直在这个论坛上问,但我没有找到我需要的那个。 我的问题是我有一个这样的复合类

class Customer
{
   private int Id { set; get; } 
   private int Name { set; get; }
   private Company Company { set; get; }
   ...
}

class Company
{
   private int Id { set; get; }
   private string Name { set; get; }
   ...
}

当我获得客户数据时

string sql = "SELECT cust.id, cust.name, comp.name AS [CompanyName] FROM Customer cust INNER JOIN Company comp ON cust.Company = comp.Id";
....
using (IDataReader dr = db.ExecuteReader(cmd))
{
    if (dr.Read())
    {
        customer = (Customer)FillDataRecord(dr, customer);
    }
}

并使用反射将其映射到客户类(对象),代码:

public static Object FillDataRecord(IDataRecord dr, Object obj)
{
    try
    {
        Type type = obj.GetType();
        PropertyInfo[] properties = type.GetProperties();

        for (int i = 0; i < dr.FieldCount; i++)
        {
            if (!dr[i].ToString().Equals(string.Empty))
            {
                type.GetProperty(dr.GetName(i)).SetValue(obj, dr[i], null);
            }
        }

        return obj;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

当它映射 CompanyName 时,它​​会返回错误“对象引用未设置为对象的实例”。我已经调试过,我知道问题所在,但直到现在我都无法解决。

我知道 AutoMapper 或 Dapper,但是当我申请这个案例时,我也遇到了同样的问题。

现在我正在使用 ValueInjecter,根据我的阅读,它可以解决我的问题。 但我的 cust.Id 值与 cust.Company.Id 和 cust.Name = "" 和 cust.Company.Name = ""

相同
string sql = "select cust.id, cust.name, comp.name from customer cust inner join company comp on cust.company = comp.id";

while (dr.Read())
{
   var cust = new Customer();
   cust.InjectFrom<ReaderInjection>(dr);

   cust.Company = new Company();
   cust.Company.InjectFrom<ReaderInjection>(dr);

   list.add(cust);
}

有什么问题吗?请帮帮我。

【问题讨论】:

    标签: c# object mapping system.reflection valueinjecter


    【解决方案1】:

    你为什么使用对象?为什么不让它通用?像这样:

    public static T FillDataRecord<T>(IDataRecord dr) where T : new()
    {
        T returnedInstance = new T();
        string fieldName = default(string);
    
        try
        {
            PropertyInfo[] properties = typeof(T).GetProperties();
    
            fieldName = dr.GetName(i);
    
            foreach (PropertyInfo property in properties)
            {
                if (property.Name == fieldName)
                {
                    // Handle the DBNull conversion issue..
                    if (dr.GetValue(i) == DBNull.Value)
                        property.SetValue(returnedInstance, null, null);
                    else
                        property.SetValue(returnedInstance, dr[i], null);
                }
            }
    
            return returnedInstance;
        }
        catch (Exception ex)
        {
            // Handle exception here
        }
    }
    

    那么你可以这样做:

    Customer _customer = FillDataRecord<Customer>(dr);
    

    或者,这个:

    CustomerDetails _customerDetails = FillDataRecord<CustomerDetails>(dr);
    

    回答您的问题.. 如果有可能从数据库中提取 NULL.. 您必须检查它。

    【讨论】:

    • 我对Generic知之甚少,完成后我会改进它。感谢您的改进,但由于我未在您的代码中声明变量并且字段名类型为字符串,因此出现错误?
    • 对不起,是的,fieldName 是一个字符串。
    • 没关系,但是 record.GetName(i)、record.GetValue(i) 和 record[i] 中的 i 呢?你还没有定义它
    • 抱歉.. 我是手写的:/我已经修好了。希望它现在更有意义。
    • 我的意思是,dr.GetName(i) 中的 i 是从哪里来的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多