Design review: Always instantiate via DI

This commit is contained in:
SteveSandersonMS
2016-09-01 15:51:53 +01:00
parent 61fd900974
commit f04fb8c421
9 changed files with 97 additions and 91 deletions

View File

@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.NodeServices.HostingModels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.NodeServices
{
@@ -16,48 +17,18 @@ namespace Microsoft.AspNetCore.NodeServices
public static void AddNodeServices(this IServiceCollection serviceCollection, NodeServicesOptions options)
{
serviceCollection.AddSingleton(typeof(INodeServices), serviceProvider =>
{
// Since this instance is being created through DI, we can access the IHostingEnvironment
// to populate options.ProjectPath if it wasn't explicitly specified.
var hostEnv = serviceProvider.GetRequiredService<IHostingEnvironment>();
if (string.IsNullOrEmpty(options.ProjectPath))
{
options.ProjectPath = hostEnv.ContentRootPath;
}
// Similarly, we can determine the 'is development' value from the hosting environment
options.AddDefaultEnvironmentVariables(hostEnv.IsDevelopment());
// Likewise, if no logger was specified explicitly, we should use the one from DI.
// If it doesn't provide one, CreateNodeInstance will set up a default.
if (options.NodeInstanceOutputLogger == null)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
if (loggerFactory != null)
{
options.NodeInstanceOutputLogger = loggerFactory.CreateLogger(LogCategoryName);
}
}
return new NodeServicesImpl(options, () => CreateNodeInstance(options));
});
serviceCollection.AddSingleton(
typeof(INodeServices),
serviceProvider => CreateNodeServices(serviceProvider, options));
}
public static INodeServices CreateNodeServices(NodeServicesOptions options)
public static INodeServices CreateNodeServices(IServiceProvider serviceProvider, NodeServicesOptions options)
{
return new NodeServicesImpl(options, () => CreateNodeInstance(options));
return new NodeServicesImpl(() => CreateNodeInstance(serviceProvider, options));
}
private static INodeInstance CreateNodeInstance(NodeServicesOptions options)
private static INodeInstance CreateNodeInstance(IServiceProvider serviceProvider, NodeServicesOptions options)
{
// If you've specified no logger, fall back on a default console logger
var logger = options.NodeInstanceOutputLogger;
if (logger == null)
{
logger = new ConsoleLogger(LogCategoryName, null, false);
}
if (options.NodeInstanceFactory != null)
{
// If you've explicitly supplied an INodeInstance factory, we'll use that. This is useful for
@@ -66,17 +37,51 @@ namespace Microsoft.AspNetCore.NodeServices
}
else
{
// Otherwise we'll construct the type of INodeInstance specified by the HostingModel property,
// which itself has a useful default value.
// Otherwise we'll construct the type of INodeInstance specified by the HostingModel property
// (which itself has a useful default value), plus obtain config information from the DI system.
var projectPath = options.ProjectPath;
var envVars = options.EnvironmentVariables == null
? new Dictionary<string, string>()
: new Dictionary<string, string>(options.EnvironmentVariables);
var hostEnv = serviceProvider.GetService<IHostingEnvironment>();
if (hostEnv != null)
{
// In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few
// things that you'd otherwise have to specify manually
if (string.IsNullOrEmpty(projectPath))
{
projectPath = hostEnv.ContentRootPath;
}
// Similarly, we can determine the 'is development' value from the hosting environment
if (!envVars.ContainsKey("NODE_ENV"))
{
// These strings are a de-facto standard in Node
envVars["NODE_ENV"] = hostEnv.IsDevelopment() ? "development" : "production";
}
}
// If no logger was specified explicitly, we should use the one from DI.
// If it doesn't provide one, we'll set up a default one.
var logger = options.NodeInstanceOutputLogger;
if (logger == null)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
logger = loggerFactory != null
? loggerFactory.CreateLogger(LogCategoryName)
: new ConsoleLogger(LogCategoryName, null, false);
}
switch (options.HostingModel)
{
case NodeHostingModel.Http:
return new HttpNodeInstance(options.ProjectPath, options.WatchFileExtensions, logger,
options.EnvironmentVariables, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0);
return new HttpNodeInstance(projectPath, options.WatchFileExtensions, logger,
envVars, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0);
case NodeHostingModel.Socket:
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
return new SocketNodeInstance(options.ProjectPath, options.WatchFileExtensions, pipeName, logger,
options.EnvironmentVariables, options.LaunchWithDebugging, options.DebuggingPort);
return new SocketNodeInstance(projectPath, options.WatchFileExtensions, pipeName, logger,
envVars, options.LaunchWithDebugging, options.DebuggingPort);
default:
throw new ArgumentException("Unknown hosting model: " + options.HostingModel);
}

View File

@@ -25,21 +25,5 @@ namespace Microsoft.AspNetCore.NodeServices
public bool LaunchWithDebugging { get; set; }
public IDictionary<string, string> EnvironmentVariables { get; set; }
public int? DebuggingPort { get; set; }
public NodeServicesOptions AddDefaultEnvironmentVariables(bool isDevelopmentMode)
{
if (EnvironmentVariables == null)
{
EnvironmentVariables = new Dictionary<string, string>();
}
if (!EnvironmentVariables.ContainsKey("NODE_ENV"))
{
// These strings are a de-facto standard in Node
EnvironmentVariables["NODE_ENV"] = isDevelopmentMode ? "development" : "production";
}
return this;
}
}
}