У меня есть код в общей библиотеке для поддержки интернационализации. Основная идея заключается в том, что, учитывая полное имя местоположения файла RESX, вы можете искать значения, используя расширение разметки:
resx:ResxProperty.Name="SampleApp.Common.Resources.MainWindow"
Title="{Resx Key=Window.Title}"
Icon="{Resx Key=Window.Icon}"
Чтобы найти файл RESX, существует процедура для поиска во всех сборках, как показано ниже, и она прекрасно работает, когда файл RESX находится в той же сборке, что и xaml. НО он ломается, когда это не так.
Рассмотрим структуру решения ниже, где SampleApp.Wpf имеет вызывающий XAML и зависит как от LocalizationLib, так и от SampleApp.Common.
AppDomain.CurrentDomain.GetAssemblies () не имеет SampleApp.Common во время выполнения (хотя это происходит во время разработки).
Как я могу изменить этот код, чтобы он знал о SampleApp.Common во время выполнения?
Приветствия
Berryl
Библиотечный код
/// <summary>
/// Find the assembly that contains the type
/// </summary>
/// <returns>The assembly if loaded (otherwise null)</returns>
public static Assembly FindResourceAssembly(string resxName)
{
// check the entry assembly first - this will short circuit a lot of searching
//
var assembly = Assembly.GetEntryAssembly();
if (assembly != null && HasSpecifiedResx(assembly, resxName))
return assembly;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var searchAssembly in assemblies)
{
// skip system assemblies
var name = searchAssembly.FullName;
if (_isSystemAssembly(name)) continue;
if (HasSpecifiedResx(searchAssembly, resxName))
return searchAssembly;
}
return null;
}
UPDATE
Подробнее.
SampleApp.Wpf нацелено на .net 4.0. Ниже приведены ссылки на него, отображаемые в Visual Studio.
Единственными ссылками на проекты являются Infralution.Localization.Wpf и SampleApp.Common, которые также нацелены на .Net 4.0.
Основываясь на входных данных Metro Smurf, я попытался использовать assembly.GetReferencedAssemblies (). Когда я использую этот метод, конструктор VS НЕ находит SampleApp.Common, и следующие имена AssemblyNames известны в отладчике во время выполнения:
{System.Reflection.AssemblyName[6]}
[0]: {PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[1]: {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[2]: {System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[3]: {Infralution.Localization.Wpf, Version=2.1.2.0, Culture=neutral, PublicKeyToken=547ccae517a004b5}
[4]: {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[5]: {PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
И когда я использую origional AppDomain.CurrentDomain.GetAssemblies (), конструктор знает SampleApp.Common, и эти сборки известны во время выполнения:
?AppDomain.CurrentDomain.GetAssemblies()
{System.Reflection.RuntimeAssembly[21]}
[0]: {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[1]: {Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[2]: {System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[3]: {System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[4]: {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[5]: {Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[6]: {Microsoft.VisualStudio.Debugger.Runtime, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[7]: {vshost32, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[8]: {System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[9]: {System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[10]: {System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[11]: {Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[12]: {System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[13]: {System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[14]: {System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[15]: {WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[16]: {PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[17]: {PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[18]: {SampleApp.Wpf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
[19]: {System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[20]: {Infralution.Localization.Wpf, Version=2.1.2.0, Culture=neutral, PublicKeyToken=547ccae517a004b5}
В обоих случаях SampleApp.Common не известен во время выполнения. Для удовольствия я загрузил эту сборку в отладчик и получил:
?Assembly.Load("SampleApp.Common")
{SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
[System.Reflection.RuntimeAssembly]: {SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
CodeBase: "file:///C:/.../SampleApp.Wpf/bin/Release/SampleApp.Common.DLL"
EntryPoint: null
EscapedCodeBase: "file:///C:.../SampleApp.Wpf/bin/Release/SampleApp.Common.DLL"
Evidence: {System.Security.Policy.Evidence}
FullName: "SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
GlobalAssemblyCache: false
HostContext: 0
ImageRuntimeVersion: "v4.0.30319"
IsDynamic: false
IsFullyTrusted: true
Location: "C:\\...\\SampleApp.Wpf\\bin\\Release\\SampleApp.Common.dll"
ManifestModule: {SampleApp.Common.dll}
PermissionSet: {<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
}
ReflectionOnly: false
SecurityRuleSet: Level2
Я также попробовал предложение Метро Смурфа сослаться на статическую строку из SampleApp.Common в SampleApp.Wpf. Без изменений, хотя, думаю, это еще раз доказывает, что SampleApp.Common имеет правильную ссылку.
Другие вещи, которые можно попробовать в SampleApp.Common, могут включать добавление EntryPoint, SNK или HashAlgorithm.
ИСПРАВЛЕНИЕ
asm.GetReferencedAssemblies звучит как билет, но возвращает только сборки, которые загружены в память, и сборки не загружаются, если на них нет ссылки в коде (как, впрочем, и странно, что один проект имеет ссылку на другой, но это не совсем то, что возвращает этот метод).
Оказывается, что AppDomain.CurrentDomain.GetAssemblies () работает так же.
Metro Smurf был на правильном пути, но, очевидно, статическая ссылка не загрузит сборку, а создаст экземпляр типа из сборки. Итак:
Console.WriteLine(Class1.MyDummyString) // this won't do it
Console.WriteLine(new Class1()) // finally, the assembly is loaded
Как бы мне не нравилось создавать фиктивный класс, в этом случае это легко исправить; Я могу оставить исходный код библиотеки как есть.