使用具有静态变量的DLL调用Activator.Createinstance(...)

时间:2017-12-14 20:36:44

标签: c# dll activator

我有一个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);
  }
}

1 个答案:

答案 0 :(得分: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);
    }
}