Несколько ссылок на приложения. То же. DLL [дубликат]

Если вы используете DecimalFormat для преобразования double в String, это очень просто:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

Существует несколько значений перечисления RoundingMode для выбора, в зависимости от поведение, которое вам требуется.

112
задан starblue 20 September 2009 в 19:08
поделиться

7 ответов

Я использовал решение @Mattias S. Если вы действительно хотите разрешать зависимости из одной и той же папки, попробуйте использовать «Запрос места сборки», как показано ниже. args.RequestingAssembly следует проверить на недействительность.

System.AppDomain.CurrentDomain.AssemblyResolve += (s, args) =>
{
    var loadedAssembly = System.AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName == args.Name).FirstOrDefault();
    if(loadedAssembly != null)
    {
        return loadedAssembly;
    }

    if (args.RequestingAssembly == null) return null;

    string folderPath = Path.GetDirectoryName(args.RequestingAssembly.Location);
    string rawAssemblyPath = Path.Combine(folderPath, new System.Reflection.AssemblyName(args.Name).Name);

    string assemblyPath = rawAssemblyPath + ".dll";

    if (!File.Exists(assemblyPath))
    {
        assemblyPath = rawAssemblyPath + ".exe";
        if (!File.Exists(assemblyPath)) return null;
    } 

    var assembly = System.Reflection.Assembly.LoadFrom(assemblyPath);
    return assembly;
 };
0
ответ дан Arie R 22 August 2018 в 12:33
поделиться

Обновление для Framework 4

Так как Framework 4 повышает событие AssemblyResolve и для ресурсов, на самом деле этот обработчик работает лучше. Он основан на концепции, что локализации находятся в подкаталогах приложения (один для локализации с именем культуры, то есть C: \ MyApp \ it для итальянского). Внутри есть файл ресурсов. Обработчик работает также, если локализация является регионом страны, то есть it-IT или pt-BR. В этом случае обработчик «может быть вызван несколько раз: один раз для каждой культуры в резервной цепочке» [из MSDN]. Это означает, что если мы вернем значение null для файла ресурсов «it-IT», фреймворк инициирует событие с запросом «it».

Событие hook

        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);

Обработчик событий

    Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        //This handler is called only when the common language runtime tries to bind to the assembly and fails.

        Assembly executingAssembly = Assembly.GetExecutingAssembly();

        string applicationDirectory = Path.GetDirectoryName(executingAssembly.Location);

        string[] fields = args.Name.Split(',');
        string assemblyName = fields[0];
        string assemblyCulture;
        if (fields.Length < 2)
            assemblyCulture = null;
        else
            assemblyCulture = fields[2].Substring(fields[2].IndexOf('=') + 1);


        string assemblyFileName = assemblyName + ".dll";
        string assemblyPath;

        if (assemblyName.EndsWith(".resources"))
        {
            // Specific resources are located in app subdirectories
            string resourceDirectory = Path.Combine(applicationDirectory, assemblyCulture);

            assemblyPath = Path.Combine(resourceDirectory, assemblyFileName);
        }
        else
        {
            assemblyPath = Path.Combine(applicationDirectory, assemblyFileName);
        }



        if (File.Exists(assemblyPath))
        {
            //Load the assembly from the specified path.                    
            Assembly loadingAssembly = Assembly.LoadFrom(assemblyPath);

            //Return the loaded assembly.
            return loadingAssembly;
        }
        else
        {
            return null;
        }

    }
12
ответ дан Eilistraee 22 August 2018 в 12:33
поделиться

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

Изменить (из комментария):

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);

static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
    string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
    if (!File.Exists(assemblyPath)) return null;
    Assembly assembly = Assembly.LoadFrom(assemblyPath);
    return assembly;
}
136
ответ дан Frank Rem 22 August 2018 в 12:33
поделиться
  • 1
    Спасибо, Маттиас! Это работает: AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve + = новый ResolveEventHandler (LoadFromSameFolderResolveEventHandler); static Assembly LoadFromSameFolderResolveEventHandler (object sender, ResolveEventArgs args) {string folderPath = Path.GetDirectoryName (Assembly.GetExecutingAssembly (). Location); string assemblyPath = Path.Combine (folderPath, args.Name + ".dll"); Монтажная сборка = Assembly.LoadFrom (assemblyPath); возвратная сборка; } – isobretatel 3 September 2009 в 17:03
  • 2
    Отличное решение! Вот статья, описывающая несколько других решений, в том числе это подробно: kbalertz.com/897297/… (предупреждение: его для VB, а не C # и немного старого) – Domenic 21 December 2011 в 22:51
  • 3
    Что бы вы сделали, если бы хотели «отменить»? к основному резольверу. например if (!File.Exists(asmPath)) return searchInGAC(...); – Tomer W 29 January 2017 в 23:25

Вы можете добавить пробный путь в файл .config вашего приложения, но он будет работать, только если путь обнаружения содержится в базовом каталоге вашего приложения.

49
ответ дан Mark Seemann 22 August 2018 в 12:33
поделиться
  • 1
    Спасибо, что добавил. Я видел решение AssemblyResolve так много раз, хорошо иметь другой (и более простой) вариант. – Samuel Neff 3 June 2015 в 15:01

Для пользователей C ++ / CLI, вот ответ @Mattias S '(который работает для меня):

using namespace System;
using namespace System::IO;
using namespace System::Reflection;

static Assembly ^LoadFromSameFolder(Object ^sender, ResolveEventArgs ^args)
{
    String ^folderPath = Path::GetDirectoryName(Assembly::GetExecutingAssembly()->Location);
    String ^assemblyPath = Path::Combine(folderPath, (gcnew AssemblyName(args->Name))->Name + ".dll");
    if (File::Exists(assemblyPath) == false) return nullptr;
    Assembly ^assembly = Assembly::LoadFrom(assemblyPath);
    return assembly;
}

// put this somewhere you know it will run (early, when the DLL gets loaded)
System::AppDomain ^currentDomain = AppDomain::CurrentDomain;
currentDomain->AssemblyResolve += gcnew ResolveEventHandler(LoadFromSameFolder);
6
ответ дан msarahan 22 August 2018 в 12:33
поделиться

Наилучшее объяснение самой MS :

AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    //This handler is called only when the common language runtime tries to bind to the assembly and fails.

    //Retrieve the list of referenced assemblies in an array of AssemblyName.
    Assembly MyAssembly, objExecutingAssembly;
    string strTempAssmbPath = "";

    objExecutingAssembly = Assembly.GetExecutingAssembly();
    AssemblyName[] arrReferencedAssmbNames = objExecutingAssembly.GetReferencedAssemblies();

    //Loop through the array of referenced assembly names.
    foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
    {
        //Check for the assembly names that have raised the "AssemblyResolve" event.
        if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
        {
            //Build the path of the assembly from where it has to be loaded.                
            strTempAssmbPath = "C:\\Myassemblies\\" + args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
            break;
        }

    }

    //Load the assembly from the specified path.                    
    MyAssembly = Assembly.LoadFrom(strTempAssmbPath);                   

    //Return the loaded assembly.
    return MyAssembly;          
}
8
ответ дан nawfal 22 August 2018 в 12:33
поделиться
  • 1
    AssemblyResolve для CurrentDomain, недействителен для другого домена AppDomain.CreateDomain – Kiquenet 1 December 2015 в 14:24

загляните в AppDomain.AppendPrivatePath (устаревший) или AppDomainSetup.PrivateBinPath

3
ответ дан Vincent Lidou 22 August 2018 в 12:33
поделиться
  • 1
    Из MSDN : Изменение свойств экземпляра AppDomainSetup не влияет на какой-либо существующий AppDomain. Это может повлиять только на создание нового AppDomain, когда метод CreateDomain вызывается с экземпляром AppDomainSetup в качестве параметра. – Nathan 10 August 2011 в 17:11
  • 2
    Документация AppDomain.AppendPrivatePath , по-видимому, предполагает, что она должна поддерживать динамическое расширение пути поиска AppDomain, только эта функция устарела. Если это работает, это гораздо более чистое решение, чем перегрузка AssemblyResolve. – binki 8 April 2015 в 06:01
Другие вопросы по тегам:

Похожие вопросы: