2011-07-02 2 views
4

저는 C#의 중급 언어 (IL) 생성을 가르치고 있습니다. 예를 들어 System.Windows.Forms.dll을 (를) 참조하는 방법에 대해 몇 시간 씩 정체 된 것처럼 보였습니다. http://olondono.blogspot.com/2008/02/creating-code-at-runtime.html동적으로 생성 된 어셈블리에서 GAC 어셈블리를 참조하는 방법은 무엇입니까?

에서 가장 우수한 - 예를 기반으로 내가 AppDomain.CurrentDomain.DefineDynamicAssemblySystem.Reflection.Emit를 사용하여 발생하고있어 동적 어셈블리, ... 나는 기본 TransferObjectDllGenerator 가공있어,하지만 지금은의 기존 라이브러리를 참조하고 싶습니다 (전용) 생성 된 어셈블리 내에서, 그리고 방법을 알아낼 수 없습니다.

This SO question 나를 AppDomain.CurrentDomain.AssemblyResolve 이벤트로 안내합니다. 나는 이벤트 핸들러를 구현하려고 시도했지만 결코 트리거되지 않았기 때문에 이벤트 핸들러를 완전히 잘못된 장소에 두는 것과 같이 기본적으로 멍청한 것을 수행했다고 생각한다.

올바른 방향으로 어떤 포인터가 크게 감사하겠습니다. 여기

내 주류의 ... 당신은 /는 TransferObjectDllGenerator 코드가 소리하시기 바랍니다 원하는해야하는 경우 흥미로운 비트가 // <<-- 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 

입니다 ... 너무 큰 비트 (IMHO)이 있기 때문에 나는 그것을 게시하지 않은 포럼 게시물에 대한.

미리 감사드립니다.

건배. 키이스.


편집

: 향후이 스레드를 찾는 사람을위한 작업 예제를 제공한다.

사용자 지정 AssemblyResolve 이벤트 처리기를 제공 할 필요가 없습니다. 그것은 phurphy입니다. 어셈블리 이름, 네임 스페이스, 버전 및 GUID가있는 어셈블리의 정규화 된 이름을 제공하면됩니다. 는 현재 어셈블리 및 mscorlib에있는 유형 이름을 검색합니다 지정된 어셈블리 이름이없는

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.

AssemblyQualifiedName 유형을 사용해보십시오. 여기에 .NET 4 : 당신은 당신이 원하는 행동을 얻기 위해 아무 상관이 없어야하므로

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

기본 해결 프로그램은 GAC 앱 도메인 민간 경로를 검색합니다. 해상도를 사용자 정의해야하는 경우 .NET 4에서 resolver 기능을 사용하는 AssemblyResolve 또는 new Type.GetType overload이 좋습니다. GAC 또는 winsxs 경로에서 수동으로 해결하는 것은 대개 잘못된 생각입니다. 프레임 워크에서 해결 작업을 수행하도록하십시오.

+0

감사합니다. 줄리앙, 그게 내가 누락 된 것입니다 ... 지금 코드를 업데이트하여 효과가있는 것을 보여 드리겠습니다. – corlettk