6

I'm working with the System.Web.Helpers.WebGrid in an ASP.NET MVC 3 Razor project, and I'm having trouble understanding why the format parameter for a WebGridColumn is a Func<dynamic, object>.

If I create a column like this...

grid.Column(
    format: x => string.Format("{0:d}", x.StartDate)
    );

...I don't get strong typing on the StartDate property. If I try to get around it like this...

grid.Column(
    format: (MyObjectType x) => string.Format("{0:d}", x.StartDate)
    );

...I'm told at runtime that my lambda can't be cast to a Func<dynamic, object>. Is there some way I can use a non-dynamic lambda here? Even if it's just <object, object>?

(I'm in .NET 4.0, and Func<in T, out TResult> is supposed to be contravariant on T, but I'm confused about how covariance and contravariance work with dynamic.)

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211

1 Answers1

3

As far as the type system is concerned, dynamic is the same as object.

They cannot use a strongly-typed delegate because they don't have a strongly-typed value to pass.

Inside WebGrid, they get an Object from a PropertyDescriptor, and pass that to your delegate.

Covariance won't help here; had Func<YourType, string> been convertible to Func<object, string>, it would be possible to call it with any other type and get an invalid cast.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • With object I can get an invalid cast, but with dynamic I'll get an error if `StartDate` doesn't exist at runtime. Six of one, half a dozen of the other. But as it is, if I change the `StartDate` property to, say, `InitialDate`, this MVC view will break at runtime; I won't be able to detect it even if I enable building views at compile time. – Ryan Lundy May 05 '11 at 17:58
  • @Kyralessa: You can cast in the delegate: `x => string.Format("{0:d}", ((YourType)x).StartDate)` – SLaks May 05 '11 at 18:13
  • 1
    Only in the WebGridColumn's format param, x ends up as a WebGridRow so it has to be `x => string.Format("{0:d}", ((MyType)x.Value).StartDate);`. Rather hideous. – Ryan Lundy May 05 '11 at 18:19
  • Hideous and, it seems to me, entirely unnecessary. Why didn't they use generics in the `WebGrid`? – Ryan Lundy May 05 '11 at 18:20
  • @Kyralessa: To allow it to be used with things like `DataTable`, which aren't generic. (Or with `IListSource` in generic classes) – SLaks May 05 '11 at 18:23
  • A reasonable answer, I guess, but mainly what it told me is that the WebGrid is not for a static type of guy like me. I ended up using the MvcContrib grid instead, which worked a lot better. – Ryan Lundy Aug 10 '11 at 18:20
  • @Kyralessa: See http://msdn.microsoft.com/en-us/magazine/hh288075.aspx, which shows you how to make a generic WebGrid wrapper. – SLaks Aug 10 '11 at 18:24