Если вы используете DecimalFormat
для преобразования double
в String
, это очень просто:
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
Существует несколько значений перечисления RoundingMode
для выбора, в зависимости от поведение, которое вам требуется.
Я использовал решение @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;
};
Обновление для 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;
}
}
Похоже, вы могли использовать событие 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;
}
if (!File.Exists(asmPath)) return searchInGAC(...);
– Tomer W
29 January 2017 в 23:25
Вы можете добавить пробный путь в файл .config вашего приложения, но он будет работать, только если путь обнаружения содержится в базовом каталоге вашего приложения.
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);
Наилучшее объяснение самой 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;
}
AssemblyResolve
для CurrentDomain, недействителен для другого домена AppDomain.CreateDomain
– Kiquenet
1 December 2015 в 14:24
загляните в AppDomain.AppendPrivatePath (устаревший) или AppDomainSetup.PrivateBinPath
AppDomain.AppendPrivatePath
, по-видимому, предполагает, что она должна поддерживать динамическое расширение пути поиска AppDomain
, только эта функция устарела. Если это работает, это гораздо более чистое решение, чем перегрузка AssemblyResolve
.
– binki
8 April 2015 в 06:01