
mybatisnet - issue #20
Assembly.Load(): Fails / Unable To Load Resource Via T4 Template
Using SVN version of Subversion. Custom repository library embeds the SqlMap.config file into the assembly as a resource. The following is the initialization code that is used to setup the various custom repositories (shared base class):
protected static void Initialize()
{
ConfigurationSetting configurationSetting = new ConfigurationSetting();
configurationSetting.Properties.Add("nullableInt", "int?");
string resource = String.Format("assembly://{0}/Configuration/SqlMap.config", Assembly.GetAssembly(typeof(BaseRepository)).GetName().Name);
try {
IConfigurationEngine engine = new DefaultConfigurationEngine(configurationSetting);
engine.RegisterInterpreter(new XmlConfigurationInterpreter(resource));
IMapperFactory mapperFactory = engine.BuildMapperFactory();
_sessionFactory = engine.ModelStore.SessionFactory;
_dataMapper = ((IDataMapperAccessor) mapperFactory).DataMapper;
}
catch (Exception ex) {
Exception e = ex;
while (e != null) {
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
e = e.InnerException;
}
throw;
}
However, when attempting to use the specified custom data repository in a T4 template, a System.IO.FileNotFoundException is generated with the name of the assembly containing the repository.
When tracing the problem, I discovered that if I pass in the fully qualified assembly name (Name=mydata,Version=1.0,etc) to the Assembly.Load function, it would work. My first thought was to just update the assembly:// reference with the full assembly name, however the new Uri() fails validation when creating the Uri. Instead, I updated the AssemblyResource() constructor to do a try catch, first attempting to load the resource as before and then to walk the loaded assembly references looking for a name match.
assembly = Assembly.Load(resourceAssemblyName);
change to
try {
assembly = Assembly.Load(resourceAssemblyName);
}
catch (FileNotFoundException) {
// Attempt to find assembly in loaded assembly list
int index = 0;
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
while ((assembly == null) && (index < assemblies.Length)) {
if (String.Compare(assemblies[index].GetName().Name, resourceAssemblyName) == 0) {
assembly = assemblies[index];
}
index++;
}
}
Similar changes were made to TypeResolver.cs and DbProvider.cs. There should probably be a LoadAssembly() function created in a common module shared by all projects.
When not running in the T4 context, the exception is not thrown, so I'm assuming this is a dynamic compiler issue. The additional check to find the referenced assembly for the user shouldn't adversely affect performance.
Status: New
Labels:
Type-Defect
Priority-Low