I noticed an interesting thing about .NET Generic classes while fixing a bug (Thanks Shigeru Nakagaki for logging it). He was not able to use .NET class ‘System.Collections.Generic.List’ . Here is the code he was trying.

<cfset list = CreateObject(".net","System.Collections.Generic.List")>

The proxy generator itself was throwing an error saying that this class was not found which was quite mysterious because this class is part of core .NET library. With little debugging I found the reasons which is quite fascinating.

A Generic class will have some types associated. For example, System.Collections.Generic.List<T> has one associated type ‘T’ where T will be any type like String, int or whatever. For Generic classes, the class name that .NET actually stores is different than the specified one. It actually stores the class name as <className>`<No of Types>. Notice the backquotes ‘`’? So for ‘System.Collections.Generic.List’, the actual .NET class name is “System.Collections.Generic.List`1″. Similarly for ‘System.Collections.Generic.Dictionary<T, T>’ the actual class name is ‘System.Collections.Generic.Dictionary`2′ . This is quite different from Java Generics where the type information is not written to bytecode and hence the class name never changes.

After figuring this out, I changed the code name like this (reluctantly as this is not a valid class name)

<cfset list = CreateObject(".net","System.Collections.Generic.List")>

and this time, the error was something different. The proxy got generated fine but it still complained that it could not find the class which I had expected because backquotes ‘`’ is not allowed in a java class name. (In case you are not aware, for using .NET classes in ColdFusion, we generate a java proxy for a .NET class and the invocation happens through that proxy – See my MAX 06 presentation ). The immediate question them comes is – what was the name of the proxy class that got generated? And the proxy class was generated with name “System.Collections.Generic.List__1″. Notice that backquote ‘`’ was replaced with two underscores ‘__’.

So we wanted to use ‘System.Collections.Generic.List’, but its actual .NET class name was “System.Collections.Generic.List`1″ and its java proxy name was “System.Collections.Generic.List__1″. Interesting. Isn’t it?

Now the question is – how do you use it? If you give the class name as ‘System.Collections.Generic.List`1′, the class loading will fail and if you give the class name as ‘System.Collections.Generic.List__1′ the proxy generation will not happen. The workaround for the time being is

  • Generate the proxy for required classes separately using proxy generator (jnbproxyGui.exe)
  • Use the proxy jar in assembly list of createObject
  • Use the generated java class name with ‘`’ replaced by ‘__’.

Here is a sample code that uses .NET List<String>.

<cfset eventList = CreateObject(".net","System.Collections.Generic.List__1", "dotnetProxy.jar")>
<cfset dotnetstring = createObject(".net", "System.String", "dotnetProxy.jar")>
<!--- create a List of type String --->
<cfset stringType = dotnetstring.getDotNetClass()>
<cfset eventList.init(stringType)>
 
<!--- Add Events to List --->
<cfset eventList.add("MAX")>
<cfset eventList.add("CFUNITED")>
<cfoutput>#eventList.Get_Count()#</cfoutput>

For CF9, you will not need this workaround as we will do the .net class name to java class name translation automatically.