C# 3.0 features Extension Methods, static methods which will let you extend the functionality of existing types, without having to sub-class the type or modifying the original source code.
This article discusses how to use this feature to generate Media Center Markup Language (MCML) in a re-usable and extensible way.
Let’s start by creating a very basic extension method:
public static
String ToMcml(this
string target, string
name) {
return
String.Format("<cor:String Name=\"{0}\"
String=\"{1}\"/>",
name,
target);
}
Notice the keyword “this” in front of type “string” which let’s the compiler know which type is going to be extended by this method. In this case adding a reference to the namespace where this method is implemented will add the “ToMcml” method to any instance of type string.
This lets the developer generate the MCML markup for any string in the following forms:
String
mcmlText = String.Empty;
Console.WriteLine(mcmlText.ToMcml("McmlProperty"));
Console.WriteLine("String Value".ToMcml("AnotherMcmlProperty");
After this is ready, adding overloads for additional value types is a pretty straight-forward process.
Converting Reference Types is not as easy and will require some additional code and the use of Reflection. If we want these extension methods to be really reusable we want them to be able to act over any type and not just a specific one. This means we have to resort to extending type “object”, base of any other type in the framework, and re-use any other extension method we had already implemented to convert value types, in the following way:
public static
String ToPropertySet(this object target, String name) {
String
result = String.Empty;
Type
type = target.GetType();
result += String.Format("\n <!--
Main Type Name: {0} -->", type.Name);
PropertyInfo[] propertyInfoArray =
type.GetProperties();
result += String.Format("\n <!--
Field count: {0} -->",
propertyInfoArray.Length);
foreach
(PropertyInfo propertyInfo in
propertyInfoArray) {
result += String.Format("\n <!--
{0} -->", propertyInfo.PropertyType.Name);
switch
(propertyInfo.PropertyType.Name){
case "String":
result += "\n " +
((String)propertyInfo.GetValue(target,null))
.ToMcml(propertyInfo.Name);
break;
}
}
result = String.Format("\n<Entries>{0}\n</Entries>",
result);
if (name
!= null) {
return
result = String.Format(
"<PropertySet
Name=\"{1}\">{0}\n</PropertySet>",
result,
name);
} else {
return
result = String.Format(
"<PropertySet>{0}\n</PropertySet>",
result);
}
}
Although up to this point this method will only convert properties of String type, it is not a problem to add additional conversions methods and cases for value types.
It is also possible to change the “String.Format” method calls by proper XML handling techniques; however this is beyond the purposes of this article.
Once we have a reference to the namespace where these methods are implemented, we can apply them the following way:
Declaring a new reference type (the C# 3.0 way):
public class
TestType {
public string
Name { get; set;
}
public string
ID { get; set;
}
public string
VideoUri { get; set;
}
}
Instantiating, initializing and calling the extension method:
TestType target = new TestType();
string name = "TestPropertySetName";
target.ID = "{5B1BFC9A-9BFE-42f8-9655-B736496CAA4B}";
target.Name = "TestName";
target.VideoUri = "http://www.test.com/";
Console.WriteLine(target.ToPropertySet(name));
Following the output in the console:
<PropertySet Name="TestPropertySetName">
<Entries>
<!-- Main Type Name:
TestType -->
<!-- Field count: 3 -->
<!-- String -->
<cor:String Name="Name" String="TestName"/>
<!-- String -->
<cor:String Name="ID" String="{5B1BFC9A-9BFE-42f8-9655-B736496CAA4B}"/>
<!-- String -->
<cor:String Name="VideoUri" String="http://www.test.com/"/>
</Entries>
</PropertySet>
This is a definitely useful technique for web-hosted MCML applications which backend is implemented using version 3.5 of the .NET Framework. Although this is not likely to happen any time soon, I sincerely cannot wait for it to happen J