I needed to load dynamically some controllers to the Stankins application .Dynamic like in – written in some text file, then loading them, The best reference was https://www.strathweb.com/2018/04/generic-and-dynamically-generated-controllers-in-asp-net-core-mvc/ . But it was not enough : what I wanted is to write the controller in some text file and compile and load them.
First problem ; What about the dll’s to be loaded ?
I ended up with this code :
01 02 03 04 05 06 07 08 09 10 11 12 13 | var refs= new List<MetadataReference>();
var ourRefs=Assembly.GetEntryAssembly().GetReferencedAssemblies();
foreach ( var item in ourRefs)
{
var ass=Assembly.Load(item);
refs.Add(MetadataReference.CreateFromFile(ass.Location));
}
refs.Add(MetadataReference.CreateFromFile( typeof (Attribute).Assembly.Location));
MetadataReference NetStandard = MetadataReference.CreateFromFile(Assembly.Load( "netstandard" ).Location);
refs.Add(NetStandard);
refs.Add(MetadataReference.CreateFromFile( typeof ( object ).GetTypeInfo().Assembly.Location) );
|
Second problem: where to put the errors ? The simplest option ( not the best one) is to put as comments to the end of the file – at reloading I will find them and correct
01 02 03 04 05 06 07 08 09 10 11 | using ( var ms = new MemoryStream())
{
var res = compilation.Emit(ms);
if (!res.Success)
{
string diag= string .Join(Environment.NewLine, res.Diagnostics.Select(it=>it.ToString()));
File.AppendAllText(fileName, "/*" +diag+ "*/" );
return null ;
}
}
|
( Better – to display the error inline…)
Third problem: The controlers are loaded at initial step of configuring .NET MVC Core 2.x , not later. The assembly loader /unloader will come as a feature at .NET Core 3 – so not yet. I figure up that the best solution is to re-load the application
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | static CancellationTokenSource cancel ;
static bool InternalRequestRestart;
public async static Task Main( string [] args)
{
do {
InternalRequestRestart= false ;
cancel= new CancellationTokenSource();
await CreateWebHostBuilder(args).Build().RunAsync(cancel.Token);
await Task.Delay(10);
Console.WriteLine( "restarting" );
} while (InternalRequestRestart);
}
public static void Shutdown()
{
InternalRequestRestart= true ;
cancel.Cancel();
}
|
You can find the code source for loading the controllers at https://github.com/ignatandrei/stankins/blob/master/stankinsv2/solution/StankinsV2/StankinsData/GenericControllerFeatureProvider.cs
You can find the code source for restarting the application at https://github.com/ignatandrei/stankins/blob/master/stankinsv2/solution/StankinsV2/StankinsData/Program.cs
You can test the code at https://azurestankins.azurewebsites.net/receiveData ( add a new controller , hit save and then access the route – or swagger at https://azurestankins.azurewebsites.net/swagger/index.html
– or you can try with Docker with
( for linux containers)
docker run -p 5000:5000 ignatandrei/stankins_linux
( for windows containers)
docker run -p 5000:5000 ignatandrei/stankins_linux
( restart docker if any problems)
and access http://localhost:5000/receiveData
That’s all 