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

发布于 2024-12-28 16:23:37 字数 1202 浏览 2 评论 0原文

我正在尝试使用 Dapper 与 ASP.NET SQL 成员资格提供程序表进行交互。我包装了 SqlMembershipProvider 类,并添加了一个附加方法,根据与我拥有的一些自定义表相关的特定条件来获取 MembershipUsers。

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

但是,MembershipUser 类上的 UserName 属性没有 setter。从 Dapper SqlMapper.cs 中第 1417 行左右来看,方法 GetSettableProps() 仅获取可设置的属性。

我尝试执行 MultiMap 查询来调用构造函数,但问题是传递到查询中的对象已经缺少用户名。

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

我是否可以调用 MembershipUser 类具有的自定义构造函数?

或者我可以对 Dapper 进行合理的更改来支持我的情况吗?

** < strong>更新 **

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();  
}

I'm trying to use Dapper to interface with the ASP.NET SQL Membership Provider tables. I wrapped the SqlMembershipProvider class and added an additional method to get me the MembershipUsers given a certain criteria relating to some custom tables I have.

When querying the data with Dapper, it appears that Dapper first instantiates the class with a parameter-less constructor, and then "maps" the returned columns into the properties on the object.

However, the UserName property on the MembershipUser class has a no setter. Judging from around line 1417 in the Dapper SqlMapper.cs, the method GetSettableProps() only gets settable properties.

I tried to do a MultiMap query to invoke the constructor, but the problem with that is the objects passed into the query are already missing the UserName.

I'm guessing I could modify the GetSettableProps() method, but I'm not sure if that will work, or if it will affect my existing code.

Is there anyway for me to invoke the custom constructor that the MembershipUser class has?

Or is there a reasonable change that I could make to Dapper to support my situation?

** UPDATE **

Marc's answer to use the non-generic/dynamic Query() method was correct, but for posterity, this is the method I was referring to inside 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();  
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遗失的美好 2025-01-04 16:23:37

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

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

使用它,您可以通过使用“动态”作为中间步骤来使用非默认构造函数和属性分配,无需任何更改。

I would use the non-generic Query API here...

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

Using this you can use both non-default constructors and property assignments, without any changes, by using "dynamic" as an intermediate step.

百善笑为先 2025-01-04 16:23:37

我用这个也许可以帮助别人

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

I use this maybe it's help someone

YourList = connection.Query<YourQueryClass>(Query, arg)
              .Select(f => new ClassWithConstructor(f.foo,f.bar))
              .ToList();  
对岸观火 2025-01-04 16:23:37

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

我的方法:

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() 来消除任何类型检查问题,而无需检查派生/基类型。

I came across this question and it inspired me to think a bit differently than the other answers.

My approach:

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

...

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

Using a "private" derived class (I used internal to expose it to Unit Tests, personal preference) I was able to specify one constructor that the derived class has, this can also do some mapping or business logic to get to the desired base class/params as necessary; this is useful if the only time that object should be initiated in that way is when it's pulling from the DB.

Also, can use Linq's .Cast<MyObject>() on the collection to eliminate any type check issues down the line if need be without having to check for derived/base types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文