我在一个公共库中有一些代码可以支持国际化。基本思想是,给定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?

干杯,
贝里

图书馆代码

/// <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;
}


更新

更多细节。

SampleApp.Wpf的目标是.net 4.0。下面是在Visual Studio中显示的对其的引用。



其中唯一的项目参考是Infralution.Localization.Wpf和SampleApp.Common,它们都还针对.Net 4.0。

根据Metro Smurf的输入,我尝试使用assembly.GetReferencedAssemblies()。当我使用此方法时,VS设计器找不到SampleApp.Common,并且在运行时调试器中知道以下AssemblyName:

{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}


当我使用原始的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


我还尝试了Metro Smurf的建议,以引用SampleApp.Wpf中SampleApp.Common中的静态字符串。尽管我认为它进一步证明了SampleApp.Common被正确引用,但对此没有任何更改。

在SampleApp.Common上尝试的其他操作可能包括添加EntryPoint,SNK或HashAlgorithm。

FIX

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


尽管我不喜欢创建虚拟类,但在这种情况下,这很容易解决;我可以保留原始库代码。

最佳答案

您可能要考虑使用Assembly.GetReferencedAssemblies Method。但是,如果我没记错的话,您还需要排除框架程序集。

10-04 19:44