I need some classes to initialize the Azure storage based on some conventions, in particular during the implementation of my TableStorageInitializer<TTableEntity> and, overall, its test I found a really nice issue with dynamic.
To simplify the situation a little bit have a look to this simplified implementation:
public class TableStorageInitializer<TTableEntity> where TTableEntity : class, new() { public void Initialize() { InitializeInstance(new TTableEntity()); } public void InitializeInstance(dynamic entity) { entity.PartitionKey = Guid.NewGuid().ToString(); entity.RowKey = Guid.NewGuid().ToString(); } }
To test it I’m using a private class declared inside the test class:
private class MyClass { public string PartitionKey { get; set; } public string RowKey { get; set; } public DateTime Timestamp { get; set; } }
With my very big surprise what happen is shown in this picture:
As you can see dynamic does not work. Even if the debugger can show the right type with its public properties the DLR can’t recognize it.
How solve the situation ? Well… very very easily, old-school Reflection!!!
public void InitializeInstance(object entity) { var entityType = entity.GetType(); entityType.GetProperty("PartitionKey").SetValue(entity, Guid.NewGuid().ToString(), null); entityType.GetProperty("RowKey").SetValue(entity, Guid.NewGuid().ToString(), null); }
Note: with a public class the dynamic work as expected.
Is select broken... or is this what the C#4 spec says?
ReplyDeleteIf you can find documentation about it let me know. Thanks.
ReplyDeleteLooks like a bug to me, but you'll probably find it written in some corner of the spec.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete@Andy
ReplyDeleteNo, it shouldn't.
I don't know if it's a hole but it is a very weird behavior indeed.
ReplyDeleteI struggled with this when trying to use dynamic to represent an internal subclass of a public base class from outside its assembly; the exception message was: 'baseclass' does not contain a definition for 'property'
Note that if you declare MyClass public and try to access a non-existent property the exception message would be:
'MyClass' does not....
instead of
'object' does not....
It seems that you can't use dynamic to access non-public types/members.
There is a language spec inside VS folder "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC#\Specifications\1033"
ReplyDeleteYou probably want to have a look at:
7.2 Static and Dynamic Binding
I posted a question on SO: http://stackoverflow.com/questions/2774554/is-this-a-hole-in-dynamic-binding-in-c-4
ReplyDelete