Saturday, May 12, 2007

Using C# 3.0's Extension Methods to generate MCML from Reference types

Other versions of the article:

HTM Version

XPS Version

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.


The basics: Value Types


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 to Property Sets


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.


The result: MCML


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 J

1 comment:

Darin said...

this is interesting.. I'm looking for a way to create an HTML to mcml converter, albeit a simple one. I can imagine extending htmlcontrols this way to be able to convert an existing HTML page for display within mcml. What do you think?