用Dapper调用自定义构造函数?

时间:2012-01-24 22:05:54

标签: c# reflection asp.net-membership dapper

我正在尝试使用Dapper与ASP.NET SQL Membership Provider表进行交互。我包装了SqlMembershipProvider类,并添加了一个额外的方法来获取MembershipUsers,给出了与我的一些自定义表有关的特定标准。

使用Dapper查询数据时,似乎Dapper首先使用无参数构造函数实例化该类,然后将返回的列“映射”到对象的属性中。

但是,MembershipUser类上的UserName属性没有setter。从Dapper SqlMapper.cs中的第1417行开始,方法GetSettableProps()只能获得可设置的属性。

我尝试使用MultiMap查询来调用构造函数,但问题是传递给查询的对象已经缺少UserName。

我猜我可以修改GetSettableProps()方法,但我不确定这是否有用,或者它是否会影响我现有的代码。

我有没有想要调用MembershipUser类的自定义构造函数?

或者我可以对Dapper做出合理的改变以支持我的情况吗?

** 更新 **

Marc使用非泛型/动态Query()方法的答案是正确的,但对于后人来说,这是我在Dapper中提到的方法:

static List<PropInfo> GetSettableProps(Type t)
{
    return t
          .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
          .Select(p => new PropInfo
          {
              Name = p.Name,
              Setter = p.DeclaringType == t ? p.GetSetMethod(true) : p.DeclaringType.GetProperty(p.Name).GetSetMethod(true),
              Type = p.PropertyType
          })
          .Where(info => info.Setter != null)
          .ToList();  
}

3 个答案:

答案 0 :(得分:30)

我会在这里使用非通用的查询API ...

 return connection.Query(sql, args).Select(row =>
     new AnyType((string)row.Foo, (int)row.Bar) {
         Other = (float)row.Other }).ToList();

使用此方法,您可以使用“动态”作为中间步骤,同时使用非默认构造函数和属性赋值,而无需任何更改。

答案 1 :(得分:1)

我用它可能是帮助某人

YourList = connection.Query<YourQueryClass>(Query, arg)
              .Select(f => new ClassWithConstructor(f.foo,f.bar))
              .ToList();  

答案 2 :(得分:0)

我遇到了这个问题,它激发了我与其他答案不同的思考方式。

我的方法:

internal class SqlMyObject: MyObject {
    public SqlMyObject(string foo, int bar, float other): base(foo, bar, other) { }
}

...

return connection.Query<SqlMyObject>(sql, args);

使用“私有”派生类(我使用 internal 将其公开给单元测试,个人偏好)我能够指定派生类具有的一个构造函数,这也可以做一些映射或业务逻辑根据需要获得所需的基类/参数;如果该对象应该以这种方式启动的唯一时间是从数据库中提取时,这将很有用。

此外,如果需要,可以在集合上使用 Linq 的 .Cast<MyObject>() 以消除任何类型检查问题,而无需检查派生/基类型。