C# 使用反射和ValueInjector映射复合对象

C# 使用反射和ValueInjector映射复合对象,c#,object,mapping,system.reflection,valueinjecter,C#,Object,Mapping,System.reflection,Valueinjecter,也许这个问题在这个论坛上经常被问到,但我找不到我需要的。 我的问题是我有一个这样的复合类 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

也许这个问题在这个论坛上经常被问到,但我找不到我需要的。 我的问题是我有一个这样的复合类

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;
    }
}
公共静态对象FillDataRecord(IDataRecord dr,对象obj)
{
尝试
{
Type Type=obj.GetType();
PropertyInfo[]properties=type.GetProperties();
对于(int i=0;i
当映射CompanyName时,它将返回错误“对象引用未设置为对象的实例”。我已经调试过了,我知道这个问题,但直到现在,我还不能解决它

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

现在我正在使用ValueInjector,据我所知,它可以解决我的问题。 但我的cust.Id值与cust.Company.Id、cust.Name=“”和cust.Company.Name=“”相同

string sql=“从cust.company=comp.id上的客户客户内部加入公司comp中选择cust.id、cust.name、comp.name”;
while(dr.Read())
{
var cust=新客户();
客户(dr);
客户公司=新公司();
客户公司(dr);
列表。添加(客户);
}

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

为什么要使用Object?为什么不让它通用?像这样:

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
    }
}
公共静态T FillDataRecord(IDataRecord dr),其中T:new()
{
T returnedInstance=新的T();
字符串字段名=默认值(字符串);
尝试
{
PropertyInfo[]properties=typeof(T).GetProperties();
fieldName=dr.GetName(i);
foreach(属性中的PropertyInfo属性)
{
if(property.Name==fieldName)
{
//处理DBNull转换问题。。
if(dr.GetValue(i)=DBNull.Value)
SetValue(returnedInstance,null,null);
其他的
SetValue(returnedInstance,dr[i],null);
}
}
回归立场;
}
捕获(例外情况除外)
{
//在这里处理异常
}
}
然后你可以这样做:

Customer _customer = FillDataRecord<Customer>(dr);
Customer\u Customer=FillDataRecord(dr);
或者,这是:

CustomerDetails _customerDetails = FillDataRecord<CustomerDetails>(dr);
CustomerDetails\u CustomerDetails=FillDataRecord(dr);

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

我对通用的了解很少,完成后我会改进它。谢谢您的改进,但我遇到了错误,因为变量我没有在您的代码中声明,fieldname类型是字符串吗?我很抱歉,是的,fieldname是字符串。没关系,但是record.GetName(I)、record.GetValue(I)和record[I]中的I呢?你不是在用考古学来定义它。。我手工打出来的:/我已经搞定了。我的意思是,在dr.GetName(我)中我来自哪里?
CustomerDetails _customerDetails = FillDataRecord<CustomerDetails>(dr);