c # .NET Загрузка / выгрузка сборки при сохранении того же сеанса

Я новичок в C # и .NET и пытаюсь создать веб-приложение asp.net, которое динамически загружает сборку.

Первоначально я использовал Activator.CreateInstance для динамической загрузки сборок, но похоже, что это блокирует файл DLL сборки. Поскольку я вношу частые изменения в сборку, это стало настоящей болью. Мне также нужно поделиться сборкой с другими приложениями, так что позже это может стать проблемой.

Похоже, что большинство людей рекомендуют создать отдельный домен приложения и загрузить в него сборку, а затем выгрузить домен приложения после того, как я закончу. Однако мое приложение и сборка также зависят от контекста сеанса, и весь сеанс теряется, когда я отправляю его в домен приложения; сборка вылетает, потому что не может найти контекст сеанса.

Есть ли способ передать контекст моего сеанса в AppDomain? Или у меня есть способ загрузить сборку без блокировки файла DLL? Я попытался передать файл в потоковом режиме, как некоторые предлагали, но он по-прежнему блокирует DLL.

Изменить: я пробовал следующий код, как предложил Давид Пирас, но файл DLL все еще заблокирован

    private static T CreateInstance<T>(string fileName, string typeName)
    {
        if (!File.Exists(fileName)) throw new FileNotFoundException(string.Format("Cannot find assembly '{0}'.", fileName));

        try
        {
            Assembly assembly = Assembly.LoadFrom(fileName);
            if (assembly != null)
            {
                List<Type> assemblyTypes = assembly.GetTypes().ToList();

                Type assemblyType =
                    assemblyTypes.FirstOrDefault(asmType => typeof(T).IsAssignableFrom(asmType));
                T instance = (T) Activator.CreateInstance(assemblyType);

                if (instance != null) return instance;

            }
            // Trouble if the above doesn't work!
            throw new NullReferenceException(string.Format("Could not create type '{0}'.", typeName));
        }
        catch (Exception exp1)
        {
            throw new Exception("Cannot create instance from " + fileName + ", with type " + typeName + ": " + exp1.Message + exp1.Source, exp1.InnerException);
        }

    }

person Koss    schedule 08.09.2011    source источник
comment
см. мое редактирование и скоро появится еще код :)   -  person Davide Piras    schedule 09.09.2011


Ответы (1)


чтобы загрузить сборки в один и тот же домен приложения, но не заблокировать файлы после загрузки, просто используйте метод LoadFrom следующим образом:

Assembly asm = Assembly.LoadFrom( “mydll.dll” );

Таким образом, вы закончите, и сеанс будет доступен.

возникнет проблема с отладчиком, потому что символы (* .pdb) не будут загружены, поэтому точка останова и отладка недоступны, чтобы иметь возможность отлаживать, вы должны действительно загрузить файлы .pdb в память, например, используя FileStream.

Изменить: Вы можете также загружать символы и не блокировать файлы, используя правильную перегрузку Assembly.Load, которая получает два байта [], один для сборки, а другой для файл символов сборки (файл .pdb):

public static Assembly Load(
    byte[] rawAssembly,
    byte[] rawSymbolStore
)

на самом деле вы должны сначала загрузить байты с потоком, затем вызвать Assembly.Load и передать byte []

ИЗМЕНИТЬ 2:

вот полный пример загрузки сборок в вашем текущем домене, включая файл символов и без блокировок файлов.

это полный пример, найденный в Интернете, он отражает все, что вам нужно, включая обработку AppDomain.AssemblyResolve ...

public static void Main() {
      AppDomain currentDomain = AppDomain.CurrentDomain;

      currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolver);
   }

   static void InstantiateMyType(AppDomain domain) {
      try {
     // You must supply a valid fully qualified assembly name here.
         domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyType");
      } catch (Exception e) {
         Console.WriteLine(e.Message);
      }
   }

   // Loads the content of a file to a byte array. 
   static byte[] loadFile(string filename) {
      FileStream fs = new FileStream(filename, FileMode.Open);
      byte[] buffer = new byte[(int) fs.Length];
      fs.Read(buffer, 0, buffer.Length);
      fs.Close();

      return buffer;
   }   

   static Assembly MyResolver(object sender, ResolveEventArgs args) {
      AppDomain domain = (AppDomain) sender;

      // Once the files are generated, this call is
      // actually no longer necessary.
      EmitAssembly(domain);

      byte[] rawAssembly = loadFile("temp.dll");
      byte[] rawSymbolStore = loadFile("temp.pdb");
      Assembly assembly = domain.Load(rawAssembly, rawSymbolStore);

      return assembly;
   }
person Davide Piras    schedule 08.09.2011
comment
а разгрузка? Я имею в виду, что это то, что меня интересует .... Как насчет этого, мы проверяем, загружен ли уже сборщик, а если нет, то загружаем его. И когда захотим, легко разгрузимся. - person KMX; 30.06.2013
comment
Afaik, по крайней мере, до .net 2 не было возможности выгрузить сборку, однажды добавленную в домен приложения. Так что он будет выгружен только тогда, когда вы выгрузите домен. - person Davide Piras; 01.07.2013
comment
метод loadFile можно заменить на File.ReadAllBytes () - person staafl; 16.10.2014