我想要一个Web服务,允许您动态添加/修改控制器代码而无需重新编译。
我已经找到了使用DefaultHttpControllerSelector执行此操作的方法,但这在.NET核心中不起作用。我也发现使用IApplicationModelConvention做类似的事情,但这只允许你在启动时添加新的控制器。使用DefaultHttpControllerSelector,您无需重新编译即可完成所有操作。 (以下示例来自https://www.strathweb.com/2013/03/leveraging-roslyn-to-author-asp-net-web-api-without-recompiling/)
public class NoCacheSelector : DefaultHttpControllerSelector
{
private readonly HttpConfiguration _configuration;
private const string Controllers = @"C:UsersFilipDocumentsVisual Studio 2012ProjectsMvcApplication6MvcApplication6Controllers";
private const string Models = @"C:UsersFilipDocumentsVisual Studio 2012ProjectsMvcApplication6MvcApplication6Models";
public NoCacheSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
var controllers = Directory.GetFiles(Controllers);
var models = Directory.GetFiles(Models);
var metadataReferences = controllers.Select(i => SyntaxTree.ParseFile(i)).Union(models.Select(i => SyntaxTree.ParseFile(i)));
var compiledCode = Compilation.Create(
outputName: "controllersAndModels.dll",
options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: metadataReferences,
references: new[] {
new MetadataFileReference(typeof(object).Assembly.Location),
new MetadataFileReference(typeof(Enumerable).Assembly.Location),
new MetadataFileReference(typeof(ApiController).Assembly.Location),
});
Assembly assembly;
using (var stream = new MemoryStream())
{
compiledCode.Emit(stream);
assembly = Assembly.Load(stream.GetBuffer());
}
var types = assembly.GetTypes();
var matchedTypes = types.Where(i => typeof(IHttpController).IsAssignableFrom(i)).ToList();
var controllerName = base.GetControllerName(request);
var matchedController = matchedTypes.FirstOrDefault(i => i.Name.ToLower() == controllerName.ToLower() + "controller");
return new HttpControllerDescriptor(_configuration, controllerName, matchedController);
}
}