#c# #assemblies #load #gac
#c# #сборки #загрузить #gac
Вопрос:
Я знаю, как загрузить сборку из имени файла, а также из GAC. Поскольку мой файл .msi поместит проект dll в GAC, мне интересно, возможно ли загрузить его из GAC, не зная полного имени (я имею в виду только с именем сборки или даже с именем файла dll), потому что я должен загрузить эту сборку из другого проекта.
Комментарии:
1. Вот какая сборка. LoadWithPartialName() был разработан для выполнения. Большой [Устаревший] для этого с версии 2.0, и это справедливо.
Ответ №1:
Вот фрагмент кода, который позволяет это сделать, и пример:
string path = GetAssemblyPath("System.DirectoryServices");
Assembly.LoadFrom(path);
Примечание. если вам нужна определенная архитектура процессора, поскольку она поддерживает частичное имя, вы можете написать что-то подобное:
// load from the 32-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=X86");
// load from the 64-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=AMD64");
Это реализация:
/// <summary>
/// Gets an assembly path from the GAC given a partial name.
/// </summary>
/// <param name="name">An assembly partial name. May not be null.</param>
/// <returns>
/// The assembly path if found; otherwise null;
/// </returns>
public static string GetAssemblyPath(string name)
{
if (name == null)
throw new ArgumentNullException("name");
string finalName = name;
AssemblyInfo aInfo = new AssemblyInfo();
aInfo.cchBuf = 1024; // should be fine...
aInfo.currentAssemblyPath = new String('', aInfo.cchBuf);
IAssemblyCache ac;
int hr = CreateAssemblyCache(out ac, 0);
if (hr >= 0)
{
hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
if (hr < 0)
return null;
}
return aInfo.currentAssemblyPath;
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
private interface IAssemblyCache
{
void Reserved0();
[PreserveSig]
int QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo);
}
[StructLayout(LayoutKind.Sequential)]
private struct AssemblyInfo
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public string currentAssemblyPath;
public int cchBuf; // size of path buf.
}
[DllImport("fusion.dll")]
private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);
Комментарии:
1. Вау! Это кажется сложным! Я искал что-то более простое, но ИМХО решение, которое вы предлагаете, безусловно, лучшее для достижения этого! Спасибо, я попробую это, если когда-нибудь моя потребность станет обязательной!
2. Потрясающая работа, Саймон. Я использовал этот ответ для класса TypeResolver, как описано в Code Project : codeproject.com/Articles/641878 /…
Ответ №2:
Да, в этом весь смысл GAC. Среда выполнения сначала просмотрит GAC, даже не заглядывая в текущий каталог.
Комментарии:
1. Спасибо вам за эту деталь, но мне было интересно, можно ли сделать какой-нибудь трюк, например,
Assembly.Load("myAssembly")
вместоAssembly.Load("myAssembly, Version=xxxxx, PublicKeyToken=xxxxxx")
ИМХО, это невозможно, но сейчас я ищу способ узнать имя сборки основного вывода в моем MSI и поместить его в app.config, чтобы динамически получать имя сборки в коде.