I am currently looking at optimising an C# (.NET 3.5) application framework, and at the moment I am looking at portions of the code that use Activator.CreateInstance to invoke assembly methods via interfaces. As an example I have the following the following, fully functional, code:
private object InvokeAssembly(string assemblyPath, string assemblyType, string data)
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type type = assembly.GetType(assemblyType, true, true);
IMyInterface assemblyInterface = (IMyInterface)Activator.CreateInstance(type);
return assemblyInterface.DoSomething(data);
}
The question is, is that a good design? Especially when considering that this particular method is called 100’s of times a minute, so would the following singleton-esque pattern be a better design?
Improved sample code, courtesy of JaredPar
Dictionary<string, IMyInterface> assemblyCache = new Dictionary<string, IMyInterface>();
private object InvokeAssembly(string assemblyPath, string assemblyType, string data)
{
var cacheKey = assemblyPath + "*" + assemblyType;
IMyInterface assemblyInterface;
if (!this.assemblyCache.TryGetValue(cacheKey, out assemblyInterface))
{
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type type = assembly.GetType(assemblyType, true, true);
assemblyInterface = (IMyInterface)Activator.CreateInstance(type);
assemblyCache[cacheKey] = assemblyInterface;
}
return assemblyInterface.DoSomething(data);
}
In this second example the interface is created once and reused rather than created/collected once per request.
It seems logical that the second method is the better solution, however I am more than happy to be told that it makes no difference.
It is also worth mention that this method and only this method operates on the Assembly
The second solution will perform better but has a bug. It cache’s the
IMyInterfaceinstance and reuses it across method calls without bothering to check that the same assembly path and type were passed into the method. Consequetive calls with differentpathortypevalues will cause the wrongIMyInterfaceinstance to be used. The caching pattern needs to be aware of this.One way to do this is to use a
Dictionary<string, IMyInterface>to cache the types.