2011-07-02 94 views
4

我在教自己C#中的中間語言(IL)生成,我一直堅持幾個小時,看起來像天,如何從System.Windows.Forms.dll(例如)從動態程序,其中我使用AppDomain.CurrentDomain.DefineDynamicAssemblySystem.Reflection.Emit產生...基於最優,例如在http://olondono.blogspot.com/2008/02/creating-code-at-runtime.html如何從動態生成的程序集中引用GAC程序集?

我已經有了一個基本的TransferObjectDllGenerator工作,但現在我想引用從現有的庫(僅)在生成的程序集中,並且無法弄清楚。

This SO question將我引向AppDomain.CurrentDomain.AssemblyResolve事件。我嘗試實現一個事件處理程序,但它從來沒有觸發,所以我想我已經做了一些基本愚蠢的事情,比如把事件處理程序放在完全錯誤的地方?

任何指針在正確的方向將不勝感激。

這裏是我的主線......有趣的位是// <<-- Commented thus

using System; 
using System.Reflection; 
//using System.Windows.Forms; (and removed the project's Reference to System.Windows.Forms) 

namespace ILGen 
{ 
/// <summary> 
/// Generates .\bin\$whatever\PersonLibrary.dll containing MSIL equivalent to: 
/// namespace PersonLibrary { 
///  public class Person { 
///  public string FirstName { get; set; } 
///  public string LastName { get; set; } 
///  public Person() { } 
///  public Person(string firstname, string lastname) { 
///   FirstName = firstname; 
///   LastName = lastname; 
///  } 
///  } //end-class 
/// } //end-namespace 
/// </summary> 
public class Program 
{ 
    public static void Main(String[] args) { 
     AppDomain.CurrentDomain.AssemblyResolve += MyAssemblyResolver; // <<-- Hook the "resolve this assembly" event. 
     try { 
      var dll = new TransferObjectDllGenerator("PersonLibrary"); 
      dll.AddClass("Person", new[] { 
       new Property("FirstName", typeof(string)) 
       , new Property("LastName", typeof(string)) 
       , new Property("OK", Type.GetType("System.Windows.Forms.Button")) // <<-- References System.Windows.Forms.dll; Type.GetType returns null. 
      }); 
      Console.WriteLine("Generated: " + dll.Save()); 
     } finally { 
      AppDomain.CurrentDomain.AssemblyResolve -= MyAssemblyResolver; // <<-- Unhook the "resolve this assembly" event. 
     } 
    } 

    static Assembly MyAssemblyResolver(object sender, ResolveEventArgs args) // <<-- Handle the "resolve this assembly" event. 
    { 
     if (args.Name.StartsWith("System.Windows.Forms.")) // <<-- Breakpoint here, which is never reached. 
      return Assembly.LoadFrom(@"C:\Windows\winsxs\msil_system.windows.forms_b77a5c561934e089_6.0.6001.22230_none_1a2132e45d2f30fc\System.Windows.Forms.dll"); 
     return null; 
    } 
} // end-class 
} // end-namespace 

如果您需要/想TransferObjectDllGenerator代碼請喊......因爲這是一個有點過大(恕我直言)我還沒貼吧爲論壇帖子。

提前感謝您的時間。

乾杯。基思。


編輯:提供的人誰在將來發現這個線程的工作示例。

沒有必要提供自定義的AssemblyResolve事件處理程序。那是一個phurphy。我們只需要提供程序集的完全限定名稱以及程序集名稱,名稱空間,版本和GUID。

using System; 
using System.Reflection; 

namespace ILGen 
{ 
public class Program 
{ 
    public static void Main(String[] args) { 
     var dll = new TransferObjectDllGenerator("PersonLibrary"); 
     // We need to provide the fully-qualified-assembly-name to 
     // make the standard assembly-resolver search the GAC. 
     // Thanks to Julien Lebosquain for pointing this out. 
     Type buttonType = Type.GetType(
      "System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 
     dll.AddClass("Person", new[] { 
      new Property("FirstName", typeof(string)) 
      , new Property("LastName", typeof(string)) 
      , new Property("OK", buttonType) 
     }); 
     Console.WriteLine("Generated: " + dll.Save()); 
    } 
} // end-class 
} // end-namespace 

回答

4

Type.GetType沒有指定將僅在當前組件和在mscorlib程序搜索類型名稱的集名稱。

嘗試使用該類型的AssemblyQualifiedName。這裏是.NET 4:

Type.GetType("System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") 

默認的解析器將在GAC和應用程序域私人路徑搜索,所以你應該什麼都沒有做,以得到你想要的行爲。如果您必須自定義分辨率,則需要使用.NET 4中的解析器函數AssemblyResolvenew Type.GetType overload。請注意,從GAC或winsxs路徑手動解析通常是一個糟糕的主意:讓框架完成解決工作。

+0

謝謝Julien,那正是我所缺少的......我現在更新代碼以顯示工作。 – corlettk

相關問題