views:

56

answers:

3

My target is below scenario:

  • I started application (Win32)

  • The application uses a set of classes from some .NET Class library.

  • I change some code in this .NET Class library, compile new dll

  • In my running application i destruct all the objects from this library and reload it.

  • My app is still running and all code changes are done!

I suppose that Spiring.NET (or similar framework) provides such functionality and need Your help.

Thanks a lot!

A: 

why u want to change dll, Spring implements IOC also u can do this with EntLib in entlib u can see the way of implementation (open source project), it just handles some actions not changing in dll, if u want change some code automatically use text template for compiling code dynamically use CodeDom .

SaeedAlg
+1  A: 

You can not unload an assembly once you loaded it. You can however unload an AppDomain. So the way this is done in .NET is to load that assembly in a seprate AppDomain that later can be unloaded again. Here is a simple example how to do it.

However, this approach has the downside that the objects you want to call from the other assembly must derive from MarshalByRefObject Alternatively you could use the System.Addin framework.

bitbonk
A: 

bitbonk's answer, plus some example code, including both dynamically compiling and loading. but here i used guids because when i tried to compile the existing dll, after unloding the related appdomain of course, i had an error saying that the assembly was in use. i could not figure it out, and had to compile a new dll each time. but that is ok with my application. if you achive to recompile the exsting dll please contact me.

  string tempLib = System.Guid.NewGuid().ToString() ;
  // Let's say txtIndicator is the textbox that executable code is written;
  if (txtIndicator.Text.Trim() == "") return;
  StreamWriter sw = new StreamWriter(LibPath + '\\' + txtIndicator.Text + ".cs", false);
  sw.Write(txtSource.Text);
  sw.Flush();
  sw.Close();
  CSharpCodeProvider csCompiler = new CSharpCodeProvider();
  CompilerParameters compilerParams = new CompilerParameters();
  compilerParams.OutputAssembly = AppDomain.CurrentDomain.BaseDirectory+"\\"+tempLib+".dll";
  compilerParams.ReferencedAssemblies.Add("system.dll");
  compilerParams.ReferencedAssemblies.Add("other assemblies");
  compilerParams.GenerateExecutable = false;
  compilerParams.IncludeDebugInformation = false;
  // this is necessary if you are working with native dll.
  compilerParams.CompilerOptions = "/platform:x86 /optimize";
  CompilerResults cr = csCompiler.CompileAssemblyFromFile(compilerParams,Directory.GetFiles(LibPath));
  if (cr.Errors.Count > 0)
  {
    listError.Items.Clear();
    foreach (string s in cr.Output)
      listError.Items.Add(s);
      return;
  }
  string CurrentLibrary = compilerParams.OutputAssembly;
  csCompiler.Dispose();
  csCompiler = null;


  AppDomainSetup ads = new AppDomainSetup();
  ads.DisallowBindingRedirects = false;
  ads.DisallowCodeDownload = true;
  ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

  AppDomain newdomain = AppDomain.CreateDomain("NEWDOMAIN",null,ads);

  StreamReader sr = new StreamReader(CurrentLibrary);
  byte[] byt = new byte[sr.BaseStream.Length];
  sr.BaseStream.Read(byt, 0, byt.Length);

  sr.Close();
  sr.Dispose();

  Assembly ass = newdomain.Load(byt);

  AClassInAssembly ind = (AClassInAssembly)ass.CreateInstance("NameSpaceInAssembly.ClassName", true, BindingFlags.Default, null, new object[] { /*params*/ }, null, null);
  /*Do some work*/
  //
  //

  ass = null;
  AppDomain.Unload(newdomain);     
  newdomain = null;
bahadir