Why does DapperRow.GetType () return null?

As far as I knew, Object.GetType () should never return null. ( discussion )

Dapper.Query () returns private instances of the DapperRow class to be treated as dynamic objects. I found a strange thing: DapperRow.GetType () returns null.

Here's a sample code to reproduce the problem. Create a C # project, Dapper reference and open a connection to SQL Server (or other database), use .Query () to execute a simple select query and get the first row of result. Use GetType () to get the type of the result object, the return value is null.

using (SqlConnection cn = new SqlConnection(csSql))
{
    var rec = cn.Query("select getdate() as D").Single();
    var t = rec.GetType(); // t == null
    Console.WriteLine(t.Name); // null reference exception
}

      

enter image description here

I suspect dynamic or private type is causing null, so I write my class library for the test:

namespace Lib
{
  public class Blah
  {
    public static dynamic SecretObject;
    static Blah()
    {
        SecretObject = new PrivateType();
    }
  }
  class PrivateType
  {
  }
} 

      

In another project, get a static field of dynamic type and call GetType ():

    dynamic obj = Lib.Blah.SecretObject;
    Console.WriteLine(obj.GetType().Name); // "Lib.PrivateType"

      

According to the test result even the private type as dynamic, I can still get the private type information from GetType (), why does DapperRow.GetType () return null?

+3


source to share


1 answer


DapperRow

specially built and used by Dapper to provide highly optimized strings without repeating header information. This will help you configure the size of the object and reduce redundant data, making it more efficient.

However, it would seem that the StackExchange team has taken metaprogramming even further than at first glance.

DapperRow

implements an interface System.Dynamic.IDynamicMetaObjectProvide

that requires the GetMetaObject method to be implemented :

System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(
    System.Linq.Expressions.Expression parameter)
{
    return new DapperRowMetaObject(parameter, 
        System.Dynamic.BindingRestrictions.Empty, this);
}

      

DapperRowMetaObject

is a custom implementation DynamicMetaObject

that essentially captures and overrides what methods can be called against a dynamic type and what those calls should translate. In this case, calls to anything other than the DapperRow IDictionary.Item getter or getter DapperRow.SetValue

fail because they are always routed to the two calls, but the value will defaulted to null for any "get" calls where the target property does not exist in the table.

public bool TryGetValue(string name, out object value)
{
    var index = table.IndexOfName(name);
    if (index < 0)
    { // doesn't exist
        value = null;
        return false;
    }
    ...
}

      



At this point, any methods called with a null dynamic value will throw RuntimeBinderException

:

RuntimeBinderException: Unable to execute runtime binding when null Reference

You can easily test this hypothesis by replacing it GetType()

with another call that throws the same exception:

var rec = cn.Query("select getdate() as D").Single();
var t = rec.AsEnumerable();
Console.WriteLine(t.ToList());

      

Keep in mind that information about the base type of properties on the dynamic object itself can be accessed directly:

var rec = cn.Query("select getdate() as D").Single();
var t = rec.D.GetType();
Console.WriteLine(t.Name);

      

+5


source







All Articles