2012-04-24 38 views
0

我們有一個作業服務器,用於處理從網站提交的作業。網站的程序集打包並作爲作業的一部分(包括所有衛星資源程序集)提交給作業服務器。快照給定資源的所有資源值運行時密鑰

在作業處理開始之前,這些程序集通過Assembly.Load(byte [])加載。

在作業處理過程中,我們達到了想要快照資源字符串(即驗證消息)的地步。請注意,簡單地存儲資源密鑰不是一種選擇,因爲驗證規則/消息可能會隨時間而改變,如果他們回來查看以前處理的作業/消息,我不希望顯示「最新」資源字符串。我需要顯示作業處理時的值。我需要每個支持的文化信息的快照,以便我可以在運行網站線索的適當文化中顯示消息。

要嘗試和檢索信息,網站裝配指定哪些語言環境支持,所以作業服務器上,我做這樣的事情來創建網站集的ResourceManager的:

var resourceType = Type.GetType("BTR.Websites.MadHatter.Clients.ABCCorp.Resources.ClientStrings"); 
var rm = resourceType != null ? new ResourceManager(resourceType) : null; 

這工作正常的我得到一個ResourceManager,但是,給定的XElement有效性規則和一個字符串[]的語言環境,下面的代碼「不工作」:

validationRule.Add( 
    from l in locales 
    let message = rm.GetString(p.Value.ToString(), new CultureInfo(l)) 
    select new XAttribute(string.Format("Message.{0}", l), message)); 

從本質上講,無論怎樣的CultureInfo我通過,我得到默認的(恩美國)文化的信息。

AppDomain.CurrentDomain.GetAssemblies()表示兩個網站組件和衛星組件加載:

{ABCCorp.ServiceModel,版本= 6.0.4497.18334文化=中性公鑰=空} System.Reflection.Assembly { System.Reflection.RuntimeAssembly} { ABCCorp.ServiceModel.resources,版本= 6.0.4497.18334文化= FR-FR,公鑰=空} {System.Reflection.Assembly} System.Reflection.RuntimeAssembly

但如果我嘗試以下在觀察窗口中(與上面的代碼相同),我得到en-US版本:

rm.GetString(「ResourceKey」,new CultureInfo(「fr-FR」))

最後,大概我們都熟悉LINQPad :)下面的腳本'工作'。我沒有任何對ABCCorp的ServiceModel.dll或衛星DLL的引用。

Assembly.LoadFile(@"C:\BTR\Source\ABCCorp.ServiceModel.dll"); 
Assembly.LoadFile(@"C:\BTR\Source\fr-FR\ABCCorp.ServiceModel.resources.dll"); 
AppDomain.CurrentDomain.GetAssemblies().Dump(); 
var resourceType = Type.GetType("BTR.Websites.MadHatter.Clients.ABCCorp.Resources.ClientStrings, ABCCorp.ServiceModel").Dump(); 
var rm = resourceType != null ? new ResourceManager(resourceType) : null; 
rm.GetString("FlatMemberInformationBasicInformation_DateDeathProof", new CultureInfo("fr-FR")).Dump(); 

任何建議將非常感激。

更新: 根據喬的建議,這裏是我們結束的代碼。 byte []內容是一個包含網站程序集和所有衛星資源程序集(如果有)的zip文件。

private Assembly LoadPackagedAssembly(byte[] content) 
{ 
    var loaded = new Dictionary<string, Assembly>(); 

    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) 
    { 
     return loaded.ContainsKey(args.Name) 
      ? loaded[ args.Name ] 
      : null; 
    }; 

    Assembly mainAssembly = null; 

    using (var stream = new MemoryStream(content)) 
    { 
     using (var zip = new ZipInputStream(stream)) 
     { 
      ZipEntry entry; 

      while ((entry = zip.GetNextEntry()) != null) 
      { 
       using (var buffer = new MemoryStream()) 
       { 
        Streams.CopyStream(zip, buffer); 

        var assembly = Assembly.Load(buffer.ToArray()); 

        loaded[ assembly.FullName ] = assembly; 

        if (mainAssembly == null) mainAssembly = assembly; 
       } 
      } 
     } 
    } 

    return mainAssembly; 
} 
+0

對於相同的文化,rm.GetResourceSet()返回什麼? – dez 2012-04-24 17:24:36

回答

0

這聽起來像是一個程序集解析問題。通過加載(byte [])和LoadFile,您最終得到no binding context。總之,要麼使用LoadFrom,要麼處理AppDomain的AssemblyResolve事件來處理這個事件。

請注意,LINQPad處理AssemblyResolve事件以平滑間接引用不同位置中的同一個DLL引起的問題。這樣做的一個副作用是它在綁定會失敗的場景中融合綁定上下文,從而使事情無法正常工作。

+0

謝謝你看着這個喬。解決了我們的問題。 – Terry 2012-04-26 18:29:02