in the project I'm currently working on, we have a number of classes that are instantiated only via reflection, and the assemblies they belong to are not referenced by any other class.
This scheme allows to replace an assembly at runtime to extend/correct the functionalities of the previous one. Please note that in our specific case it is not possible to use MarshalByRefObject, and therefore different versions of the same assembly, exposing classes with the same name but different functionalities, end up being loaded in the same AppDomain.
I present an extremely simplified example: consider the following interface declaration and console application
public interface ISomeInterface
{
string getData();
}
class Program
{
static void Main(string[] args)
{
byte[] lastLibrary = null;
Assembly lastAssembly = null;
while (true)
{
byte[] theLibrary = File.ReadAllBytes("ClassLibrary1.dll");
if (lastLibrary == null || !theLibrary.SequenceEqual(lastLibrary))
{
lastAssembly = Assembly.Load(theLibrary);
}
ISomeInterface obj = lastAssembly.CreateInstance("ClassLibrary1.Class1") as ISomeInterface;
Console.WriteLine(obj.getData());
lastLibrary = theLibrary;
Thread.Sleep(1000);
}
}
}
along with the following interface implementation (on a separate assembly):
public class Class1 : ISomeInterface
{
public string getData()
{
return "someText";
}
}
As expected, if I change the implementation of ISomeInterface (for instance, changing "someText"开发者_运维知识库 to "someOtherText") and replace the old dll with the new one, the most recent version is used. I am wondering, though: what is the chance that this mechanism will cause problems to the stability of the software? I mean, is everything safe until I am instantiating these classes via reflection only and no other component references them? As for our preliminary tests, it looks like everything is working fine, but I wanted to hear also from experts.
I know that in this specific example it would be possible to use a MarshalByRefObject to accomplish everything, but as I said before, it is not possible for us to go in that direction.
Something like this should work fine, but I think you're misunderstanding what actually happens.
When you load an assembly into an AppDomain, it is never released, as long as that AppDomin exists. What you do is to load a new assembly. But by doing that, you're not releasing the old version. For example, if an object from the previous version were still around, it would return "someText", even if a newly created object would return "someOtherText". And while the name of the type of both of these objects is ClassLibrary1.Class1
, they are different types.
If this behavior is correct for you, then you should be fine. But don't forget that all the old versions are still loaded and thus kept in memory, so doing this actually causes memory leak.
精彩评论