I created a . NET Core 3.0 project and solved my problem using Assemblyloadcontext.Unload which was suggested by Augusto Vasques:
I did it in two ways:
1: Inmemory:
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ExecuteInMemoryAssembly(Compilation compilation, int i)
{
var context = new CollectibleAssemblyLoadContext();
using (var ms = new MemoryStream())
{
var cr = compilation.Emit(ms);
ms.Seek(0, SeekOrigin.Begin);
var assembly = context.LoadFromStream(ms);
var type = assembly.GetType("CSharp");
var greetMethod = type.GetMethod("Executar");
var instance = Activator.CreateInstance(type);
var result = greetMethod.Invoke(instance, null);
}
context.Unload();
}
2: With the Dll
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ExecuteAssembly(int i, string path)
{
var context = new CollectibleAssemblyLoadContext();
var assemblyPath = Path.Combine(Directory.GetCurrentDirectory(), path);
using (var fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))
{
var assembly = context.LoadFromStream(fs);
var type = assembly.GetType("CSharp");
var method = type.GetMethod("Executar");
var instance = Activator.CreateInstance(type);
var result = method.Invoke(instance,null);
}
context.Unload();
}
Collectibleassemblyloadcontext:
public class CollectibleAssemblyLoadContext : AssemblyLoadContext
{
public CollectibleAssemblyLoadContext() : base(isCollectible: true)
{ }
protected override Assembly Load(AssemblyName assemblyName)
{
return null;
}
}
Controller:
private static Assembly SystemRuntime = Assembly.Load(new AssemblyName("System.Runtime"));
[HttpGet]
public void Get()
{
var fileName = "CSharp.dll";
var classe = "public class CSharp \r\n" +
"\t{\r\n" +
"\t\t public double Executar()\r\n" +
"\t\t{\r\n" +
"\t\t\t return 26; \r\n" +
"\t\t}\r\n" +
"}";
var compilation = CSharpCompilation.Create("DynamicAssembly", new[] { CSharpSyntaxTree.ParseText(classe) }, new[] {
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
MetadataReference.CreateFromFile(typeof(Console).GetTypeInfo().Assembly.Location),
MetadataReference.CreateFromFile(SystemRuntime.Location),
}, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
for (var i = 0; i < 3000; i++)
{
ExecuteInMemoryAssembly(compilation, i); // (1)
ExecuteAssembly(i, Path.GetFullPath(fileName)); // (2)
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
REFERENCES:
https://www.strathweb.com/2019/01/collectible-assemblies-in-net-core-3-0/
https://docs.microsoft.com/pt-br/dotnet/standard/assembly/unloadability
Do you really have to play this dynamic code within the context of the main application? Can’t you create a domain within the application that can host that dynamic(s) class(s)? Reference
AppDomain
– Augusto Vasques
I never used Appdomain... so I didn’t see it as a possibility... I did a search here, it would be more or less that?
– LeoHenrique
I will not only copy and paste, but understand what you are doing, so I want to know if it would be right to follow the link I sent
– LeoHenrique
I did not analyze in depth the link you sent, because I am working, but on top is very close to what I suggested (probably exactly my suggestion). If the use of
AppDomain
go in the direction you are looking for, the night I can give an example of how to compile, compile and discard compiled code next to the domain.– Augusto Vasques
Puts @Augustovasques, would help me a lot, thank you if you can show me yes...
– LeoHenrique
I went to write the example and I have two bad news. 1: NET Core 3 does not support multiple domains. 2: The method Assemblyloadcontext.Unload only exists in the documentation. For now the only way this code progress is in . NET 4
– Augusto Vasques
I’m using the . net 2.2
– LeoHenrique
But 'Unload' is only . net 3 ne...
– LeoHenrique
I expressed myself badly. Core . NET is one thing and . NET Framework is another. This code you wrote is for Core . NET this code will only progress in . NET Framework.
– Augusto Vasques
Let’s go continue this discussion in chat.
– LeoHenrique