2011-05-19 31 views
2
其他組件聲明的類型的字段

我有embedes的應用程序:內部本身並裝入AppDomain.CurrentDomain.AssemblyResolve事件中引用組件(稱爲ClassLibrary1的)(經由BuildAction的嵌入的資源) 。 主組件定義了一類的Class1:錯誤反序列化對象具有裝載在AssemblyResolve

public class Class1 
{   
    public Class2 MyField { get; set; }  
} 

它在ClassLibrary1的定義類型的Class2的屬性。等級2的 定義:

public class Class2 
{ 
    public int A { get; set; } 
} 

在main方法我真的創建一個新的XmlSerializer(typeof運算(1類)):

static void Main() 
    { 
     SubscribeAssemblyResolver(); 
     MainMethod(); 
    } 

    private static void MainMethod() 
    { 
     XmlSerializer xs2 = new XmlSerializer(typeof(Class1)); 
     Class1 cl = new Class1(); 
    } 

當執行PROGRAMM我得到以下錯誤:

無法生成臨時類(結果= 1)。 錯誤CS0012:類型'ClassLibrary1.Class2'是在未引用的程序集中定義的。您必須添加對程序集'ClassLibrary1,版本= 1.0.0.0,Culture = neutral,PublicKeyToken = c06f123f2868e8c8'的引用。 錯誤CS0266:不能將類型'object'隱式轉換爲'ClassLibrary1.Class2'。存在明確的轉換(您是否缺少演員?)

任何想法?

的其餘代碼:

private static void SubscribeAssemblyResolver() 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);    
    } 

    static Dictionary<String, Assembly> _assemblies = new Dictionary<String, Assembly>(StringComparer.OrdinalIgnoreCase); 

    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     return ResolveAssembly(args.Name); 
    } 

    private static Assembly ResolveAssembly(string argsName) 
    { 
     Assembly dll; 
     var name = "WindowsFormsApplication1.Libs." + new AssemblyName(argsName).Name + ".dll"; 
     if (!_assemblies.TryGetValue(name, out dll)) 
     { 
      Assembly res = typeof(Program).Assembly; 
      using (var input = res.GetManifestResourceStream(name)) 
      { 
       if (input == null) 
       { 
        //TODO: log 
        return null; 
       } 
       Byte[] assemblyData = new Byte[input.Length]; 
       input.Read(assemblyData, 0, assemblyData.Length); 
       if (null == (dll = Assembly.Load(assemblyData))) 
       { 
        //TODO: log 
        return null; 
       } 
       //TODO: log 
       _assemblies[name] = dll; 
       return dll; 
      } 
     } 
     return dll; 
    } 

UPDATE:創建一個BUG在Microsoft Connect站點。您也可以從那裏下載示例視覺stuido 2010解決方案(只展開「詳細信息」字段組),以進行復制。

+1

此錯誤不限於動態加載的程序集。請參見[在VB中的特定情況下創建XML序列化程序時出錯](https://connect.microsoft.com/VisualStudio/feedback/details/668950/error-creating-xml-serializer-in-specific-situation-in-vb)。不幸的是,除非它們對安全至關重要,否則XmlSerializer錯誤不會被修復。 – 2011-05-19 18:09:15

+0

感謝您的鏈接,約翰!不幸的是,在上述錯誤的解決方法中指定的解決方案不適用於我的情況: XmlSerializer xs2 = new XmlSerializer(typeof(Class1),new Type [] {typeof(Class2)}); 我仍然得到相同的錯誤。 – Alexzander 2011-05-19 19:24:46

+0

好吧,也許原因解決方法不適合你是因爲你的動態加載。作爲一個實驗,你可以使用靜態加載來嘗試它,並且1)看看你是否仍然得到錯誤,並且2)通過靜態加載來查看解決方法是否適用於你。如果問題是動態加載,那麼我建議你輸入一個新的Connect文章並在這裏發佈URL。 – 2011-05-20 00:52:39

回答

0

我已經通過在臨時文件夾中保存組件解決類似的問題

public static byte[] ReadFully(Stream input) 
    { 
     var buffer = new byte[16 * 1024]; 
     using (var ms = new MemoryStream()) 
     { 
      int read; 
      while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       ms.Write(buffer, 0, read); 
      } 
      return ms.ToArray(); 
     } 
    } 

    public App() 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
     { 
      var assemblyName = new AssemblyName(args.Name); 

      if (assemblyName.Name != "Omikad.Core") 
       return null; 

      var resourceName = "Terem." + assemblyName.Name + ".dll"; 

      using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 
      { 
       if (stream == null) 
        return null; 

       var assemblyData = ReadFully(stream); 
       var tmp = Path.Combine(Path.GetTempPath(), "Omikad.Core.dll"); 
       File.WriteAllBytes(tmp, assemblyData); 
       return Assembly.LoadFrom(tmp); 
      } 
     }; 
    } 
0

嘗試添加屬性附加傷害:

[XmlInclude(typeof(Class2))] 
public class Class1 
{   
    public Class2 MyField { get; set; }  
} 
+0

我已經試過了,但它不起作用,但謝謝你的迴應。 – Alexzander 2011-05-19 15:01:37

0

至於現在I`ve結束了兩個稍差的解決方案:

  1. 雖然你不能老是實例化的XmlSerializer的類型Class1的,你還是可從實例化它,以用於來自主組件的類型Class2。這意味着如果將Class1移動到主程序集的ClassLibrary1或Class2中 - 它將反序列化而不會出錯。它有效,但不可能在任何地方使用此解決方案,而且它在意識形態上是錯誤的。
  2. 使用ILMerge將這些程序集合併成一個。但它只適用於非wpf的東西,另外你應該用程序集屬性管理情況(可能會有衝突)。

而且一個非常糟糕的主意:

  1. 生成ClassLibrary1.XmlSerializer.dll與sgen.exe。
  2. 也嵌入到主要組件。
  3. 將它顯式加載到XmlSerializer緩存中,通過反射調用其內部方法之一。

雖然現在我不得不使用第一個解決方案,但我對它不滿意,因爲它太緊張了。

0

我想嘗試XmlSerializer的(類型,類型[])構造和提供的Class2作爲使用第二參數的額外類型。我幾乎沒有XmlSerializer的使用經驗,但對於DataContractSerializer來說,這是個竅門。