Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call custom constructor with Dapper?

Tags:

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();   } 
like image 223
John B Avatar asked Jan 24 '12 22:01

John B


1 Answers

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.

like image 191
Marc Gravell Avatar answered Sep 19 '22 18:09

Marc Gravell