zhaoweijing2003 / mybatisnet

Automatically exported from code.google.com/p/mybatisnet
0 stars 0 forks source link

Assembly.Load(): Fails / Unable To Load Resource Via T4 Template #20

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
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.

Original issue reported on code.google.com by ghee...@gmail.com on 13 Dec 2010 at 9:23