Late-Bound Assignment To A Field Of Value Type

Late bound resolution; runtime errors could occur

An object is assigned to a variable declared to be of the Object Data Type.

When you declare a variable as , the compiler must perform late binding, which causes extra operations at run time. It also exposes your application to potential run-time errors. For example, if you assign a Form to the variable and then try to access the XmlDocument.NameTable property, the runtime throws a MemberAccessException because the Form class does not expose a property.

If you declare the variable to be of a specific type, the compiler can perform early binding at compile time. This results in improved performance, controlled access to the members of the specific type, and better readability of your code.

By default, this message is a warning. For information on hiding warnings or treating warnings as errors, see Configuring Warnings in Visual Basic.

Error ID: BC42017

To correct this error

  • If possible, declare the variable to be of a specific type.

See Also

Early and Late Binding
Object Variable Declaration

Recently, I went on a bit of a tear in the AutoMapper trying to improve performance.  Besides the threading issues I introduced (dictionary lookups are NOT thread safe, in case you’re wondering), I looked at improving the performance of the reflection piece of AutoMapper.  At its core, I map various kinds of MemberInfo objects on source types to MemberInfo objects on destination types.  The semantic model is a little more involved of course, but that’s the basic model of going from one complex type to another.

I was quite dreading speeding up the reflection piece, not because IL generation and reflection emit isn’t interesting and all that, but it all looks quite ugly and hard to maintain.  Until I stumbled upon Nate Kohari’s post on late-bound invocations via expression trees, I was avoiding that piece.  The basic idea is that expression trees, when compiled, are able to use regular reflection MemberInfo objects to generate the right IL at runtime to do what you normally do at compile time.  If you want a good sample of how to do IL, take a look at the expression tree compilation code in Reflector.

His example worked great for methods, but AutoMapper also supports properties and fields.  To achieve the same result, I needed first to define a couple more delegate types to capture the kind of call you would do with fields and properties:

public delegate object LateBoundProperty(object target); public delegate object LateBoundField(object target);

Next, I just needed to create the expression tree for calling a field and property.  The property one is this:

public static LateBoundProperty Create(PropertyInfo property) { ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target"); MemberExpression member = Expression.Property(Expression.Convert(instanceParameter, property.DeclaringType), property); Expression<LateBoundProperty> lambda = Expression.Lambda<LateBoundProperty>( Expression.Convert(member, typeof(object)), instanceParameter ); return lambda.Compile(); }

I first create an expression that represents a call to a property (the MemberExpression instance).  Next, I need to wrap that MemberExpression call with a LambdaExpression, of type LateBoundProperty, so that I can execute the resulting delegate against any object I want.  The one for a field is quite similar:

public static LateBoundField Create(FieldInfo field) { ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target"); MemberExpression member = Expression.Field(Expression.Convert(instanceParameter, field.DeclaringType), field); Expression<LateBoundField> lambda = Expression.Lambda<LateBoundField>( Expression.Convert(member, typeof(object)), instanceParameter ); return lambda.Compile(); }

I still have a MemberExpression, but I use the Field method to create it instead.  It’s a little func-y looking, but here is what that above expression would look like, if I knew the target type at compile time:

Expression<Func<Order, decimal>> expr = o => o.Total;

I have to jump through a few more hoops, as I don’t know the in and out times at compile time, it’s all stored as reflection information.  The expression tree building doesn’t care anyway, as the above lambda syntax is merely syntactic sugar for what we wrote earlier.  But how does this perform?  As Rick Strahl points out, it only makes sense after many iterations.  But I can then do fun things like this:

public class Order { public decimal Total { get; set; } } [Test] public void Sample() { PropertyInfo propertyInfo = typeof (Order).GetProperty("Total"); var lateBoundProperty = DelegateFactory.Create(propertyInfo); var order = new Order { Total = 50m }; var total = lateBoundProperty(order); total.ShouldEqual(50m); }

Since AutoMapper already has all of the reflection information cached on a per app-domain basis (that’s why you should only configure once), I can easily go through all of the reflected information and pre-compile all of the late-bound fields, properties and methods, so that they execute very fast during a mapping operation.

So what’s the downside?  Startup is slower now, as it is CPU intensive to configure AutoMapper now.  But compared to the startup time of NHibernate and StructureMap in our applications, it does not add that much more to the total startup time.  Since we’re using AutoMapper in a web application, the we feel just as confident about its configuration time as we would NHibernate.

Unfortunately, expression trees in .NET 3.0 do not support setting fields and properties.  But since that’s changing in .NET 4.0, I think I’ll just wait to optimize the destination member assignment part of AutoMapper until then.

Categories: 1

0 Replies to “Late-Bound Assignment To A Field Of Value Type”

Leave a comment

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *