Custom ResourceLoaders in NVelocity
09 Sep 2008I needed a custom resource loader for NVelocity to enable me to unit test my new NVelocityView for the ASP.NET MVC app I was building. I studied some examples and went to work. Easy-peasy, I soon had a MemoryResourceLoader that loaded that looked something like this:
public class MemoryResourceLoader : ResourceLoader {
static IDictionary templates = new Dictionary();
public static IDictionary Templates { get { return templates; } }
public static void AddTemplate(string name, string template) {
templates[name] = Encoding.UTF8.GetBytes(template);
}
public override Stream GetResourceStream(string template) {
byte[] templateBytes;
if(!templates.TryGetValue( template, out templateBytes)) {
throw new ResourceNotFoundException(
"MemoryResourceLoader Error: cannot find resource " + template);
}
return new MemoryStream(templateBytes);
}
public override void Init(ExtendedProperties configuration) {}
public override long GetLastModified(Resource resource) {
return 0;
}
public override bool IsSourceModified(Resource resource) {
return false;
}
}
Which I tried to get NVelocity to use by going:
VelocityEngine engine = new VelocityEngine();
ExtendedProperties properties = new ExtendedProperties();
properties.AddProperty("resource.loader", "memory");
properties.AddProperty(
"memory.resource.loader.class",
"NVelocityView.MemoryResourceLoader;NVelocityView");
engine.Init(properties);
But no! All I got was:
Problem initializing template loader: NVelocityView.MemoryResourceLoader
Error is: System.ArgumentNullException: Value cannot be null.
Parameter name: type
I threw Process Monitor at it trying to figure out if it was looking for my assembly in a bisarre place, I tried fuslogvw.exe to see if there was a problem loading the assembly, I debugged and couldn’t find a solution. Until I decompiled with Reflector and noticed the somewhat strange line
loaderClassName = loaderClassName.Replace(';', ',');
in the decompiled source. Why would someone use ';'
in a type reference? Someone porting from Java of course with some strange configuration framework that uses ','
as a separator between values of course! As soon as I switched ','
to ';'
in the initialization code it was all dandy again.