Some coworker said once "Every time you hear
dynamic means a load of troubles is coming by". I didn't agree. I know lots of interesting stuff can only be done using
Reflection and even
Reflection.Emit. Just to give some context, you are talking about Microsoft Framework 4.0 and the new type
dynamic type declaration.
As you know C# is a statically typed language. As you also know, this means you must declare the type of every variable, field or property, before you can use it. The
var keyword didn't change that rule a bit. Using
var you are implicitly declaring tha variable type. The compiler knows the correct type of
var and the keyword is replaced by the correct type at
compile time.
Let's rephrase: the type of each variable, field or property must be known at
compile time. Then Framework 4.0 and _Dynamic Language Runtime_ brought us
dynamic. We must change the definition above as the real type
dynamic is unknown at compile time. A
dynamic type can be any type at all so it's legal to do any operation you like with it. The compiler won't complain about it being incorrect as it doesn't know the real type.
You can argue that
System.Object could do the the trick but you also know the range of operations you can do with
System.Object is very narrow and you have to cast it to another type in order to get the same kind of usability, I mean in order to support all operations other types support. No more limitations like that:
- declare a variable as dynamic
- your first assignmenet to this variable defines the real type it will have
- the legal or illegal operations will be evaluated after this assignement
What's the catch? Incompatibilities that couldn't show on compile time will show at runtime. So if you practice "jerk programming", you will get "a load of troubles" and my coworker's statement will prove correct.
What do I need dynamic for?
The classical problem is the "custom properties" issue. You have an business application but every customer wants its own set of extra properties and the requirements of the customer can overcome your worst scenarios/nighmares. You could go the
Reflection.Emit way but that's really hard for most programers. Let's try the
dynamic way.
Define you
CustomPropery class like this:
using System;
public class CustomProperty
{
#region Private Fields
private string _name = String.Empty;
private string _type = String.Empty;
private dynamic _value;
#endregion
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Type
{
get { return _type; }
set { _type = value; }
}
public dynamic Value
{
get { return _value; }
set { _value = value; }
}
}
Notice
dynamic is used both on the field and on the property.
I suppose you will now read the
CustomProperty definitions from some storage be it a database, XML file, it really does't matter.
Now you need a method that converts the type that you read as a
String into a
Type.
private static Type GetDataType(string type)
{
Type propType = Type.GetType(type);
if (propType == null)
propType = Type.GetType("System." + type);
if (propType == null)
propType = Type.GetType("App.CustomProperties." + type);
return propType;
}
Just to put it all together, after reading the definitions to a
prop of
PropertyInfo type, you assign the real type like this:
var customProperty = new CustomProperty();
customProperty.Name = prop.Name;
customProperty.Type = prop.PropertyType.Name;
Type targetType = GetDataType(customProperty.Type);
if (targetType != null)
{
if (targetType.IsEnum)
customProperty.Value = ConvertStringToEnum(targetType, "");
else if (targetType == typeof (Int16))
customProperty.Value = (Int16) 0;
else if (targetType == typeof (Int32))
customProperty.Value = (Int32) 0;
else if (targetType == typeof (Int64))
customProperty.Value = (Int64) 0;
}
else
{
customProperty.Value = " ";
customProperty.Value = string.Empty;
}
After the first assignement juts to define the real
Type, you can now take care of assigning the real value, knowing it will have the correct
Type.
In this example I need the properties for use in a
PropertyGrid. In each grid row, I show the
customProperty.Name followed by the
customProperty.Value. The sample presented here is very limited in scope and isn't really a How To. The point is:
- there is no keyword to define the real type of a dynamic variable/field/property
- the real type is defined by the first assignement
- do this assignment as soon as you know the real type
- assign the actual value after the previous assignment