2017-12-14 12 views
0

정적 변수가있는 DLL이 있습니다 (은 변경할 수 없습니다!)! Activator.CreateInstance(...)으로 전화를 걸었지만 이전에로드 한 인스턴스를 공유하는 대신 새로운 인스턴스를 만들려고합니다.정적 변수가있는 DLL로 Activator.Createinstance (...)를 호출합니다.

// ClassLibrary.dll 
namespace ClassLibrary 
{ 
    public class Foo 
    { 
    private static int Number { get; set; } // This is a static member... 
    public Foo() 
    { 
     Number++; 
    } 

    public int Bar() 
    { 
     return Number; 
    } 
    } 
} 

// ConsoleApplication.exe 
static int InvokeMethod() 
{ 
    var dir = Directory.GetCurrentDirectory(); 
    var path = Path.Combine(dir, "ClassLibrary.dll"); 

    var asm = Assembly.LoadFile(path); 
    var type = asm.GetType("ClassLibrary.Foo"); 
    var instance = Activator.CreateInstance(type, new object[] { }); 
    var method = type.GetMethod("Bar"); 
    return (int)method.Invoke(instance, null); 
} 

private static void Main(string[] args) 
{ 
    var val1 = InvokeMethod(); // 1 
    var val2 = InvokeMethod(); // 2! I want it to be 1 
} 

나는 AppDomain.Load()와 같은 시도했지만, 정적 값은 여전히 ​​공유되고있다.

이전에로드 한 dll을 공유하는 대신 새로운 인스턴스를로드하는 방법에 대한 제안 사항.

편집 1 : 다음은 AppDomain로드 코드이지만 결과는 같습니다.

static int InvokeMethodDomain() 
{ 
    var dir = Directory.GetCurrentDirectory(); 
    var path = Path.Combine(dir, "ClassLibrary.dll"); 

    var dom = AppDomain.CreateDomain(Guid.NewGuid().ToString()); 
    try 
    { 
    var asn = new AssemblyName {CodeBase = path}; 
    var asm = dom.Load(asn); 
    var type = asm.GetType("ClassLibrary.Foo"); 
    var instance = Activator.CreateInstance(type, new object[] { }); 
    var method = type.GetMethod("Bar"); 
    return (int) method.Invoke(instance, null); 
    } 
    finally 
    { 
    AppDomain.Unload(dom); 
    } 
} 
+0

@mjwills, 나는 같은 결과가있는 응용 프로그램 도메인으로 시도했다. AppDomain을 사용하여 예제와 함께 원래 게시물을 편집했지만 그 결과는 같습니다. –

답변

2

이미 알았 듯이 정적 값을 새로 가져 오려면 새 앱 도메인에 어셈블리를로드해야합니다. 샘플 코드 : 다음

// inherit from MarshalByRefObject to enable cross domain communication 
public class AppDomainProxy : MarshalByRefObject { 
    public int InvokeMethod() { 
     var dir = AppDomain.CurrentDomain.BaseDirectory; 
     var path = Path.Combine(dir, "ClassLibrary.dll"); 
     var asm = Assembly.LoadFile(path); 
     var type = asm.GetType("ClassLibrary.Foo"); 
     var instance = Activator.CreateInstance(type, new object[] { }); 
     var method = type.GetMethod("Bar"); 
     return (int) method.Invoke(instance, null); 
    } 
} 

그리고는 :

static int InvokeMethod() 
{    
    var appDomain = AppDomain.CreateDomain("Domain", AppDomain.CurrentDomain.Evidence, new AppDomainSetup {     
     ApplicationBase = AppDomain.CurrentDomain.BaseDirectory 
    }); 
    try { 
     // first create our proxy 
     var instance = (AppDomainProxy) appDomain.CreateInstanceAndUnwrap(
      typeof(AppDomainProxy).Assembly.FullName, 
      typeof(AppDomainProxy).FullName); 
     // this will run in new app domain 
     return instance.InvokeMethod(); 
    } 
    finally { 
     AppDomain.Unload(appDomain); 
    } 
} 
+0

완벽하고 간단한 해결책 :) –