.net - 尝试创建实例时没有合适的构造函数
问题描述
尝试使用依赖注入设置 .net 5 控制台应用程序并使用类库中的方法。不知道我已经解决了什么问题,但我得到了一个例外
'找不到适合类型'TesterUtil.DataHelper.IBookMgr'的构造函数。确保类型是具体的,并且为公共构造函数的所有参数注册了服务。
主班
class Program
{
static void Main(string[] args)
{
var host = AppStartup();
var service = ActivatorUtilities.CreateInstance<IBookMgr>(host.Services);
// test
var results = service.GetDoTest();
Console.WriteLine(results);
}
static IHost AppStartup()
{
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var configuration = new ConfigurationBuilder()
.SetBasePath(Path.GetDirectoryName(pathToExe))
.AddJsonFile("appsettings.json")
.Build();
LogManager.Configuration = new NLogLoggingConfiguration(configuration.GetSection("NLog"));
var logger = NLog.Web.NLogBuilder.ConfigureNLog(LogManager.Configuration).GetCurrentClassLogger();
logger.Info("Tester Startup");
var host = Host.CreateDefaultBuilder() // Initialising the Host
.ConfigureServices((context, services) =>
{ // Adding the DI container for configuration
services.AddTransient<IBookMgr, BookMgr>();
})
.Build(); // Build the Host
return host;
}
图书经理
public interface IBookMgr
{
public bool GetDoTest();
public bool SaveComplex();
}
public class BookMgr : IBookMgr
{
private readonly DbContextOptionsBuilder<AdhocContext> _bldr1;
private AdhocContext ctx;
public BookMgr(IConfiguration config)
{
// note extended commandtimeout settings, due to lengthy archive operations against Db
_bldr1 = new DbContextOptionsBuilder<AdhocContext>();
_bldr1.UseSqlServer(config.GetConnectionString("AdhocDbConStr"), sqlOptions => sqlOptions.CommandTimeout((int)TimeSpan.FromMinutes(20).TotalSeconds));
ctx = new AdhocContext(_bldr1.Options);
}
public bool GetDoTest()
{
// test getting data
bool retval = false;
var TestList = (from a in ctx.Book select a).ToList();
if(TestList.Count > 0)
{
retval = true;
}
else
{
retval = false;
}
return retval;
}
public bool SaveComplex()
{
bool retval = false;
return retval;
}
}
解决方案
直接从主机的服务提供者解析所需的类型,
//...
IBookMgr service = host.Services.GetRequiredService<IBookMgr>();
//...
而不是ActivatorUtilities.CreateInstance
在这种情况下,ActivatorUtilities.CreateInstance
通常用于创建具体类型的实例。
从这里的源代码可以看出
/// <summary>
/// Instantiate a type with constructor arguments provided directly and/or from an <see cref="IServiceProvider"/>.
/// </summary>
/// <param name="provider">The service provider used to resolve dependencies</param>
/// <param name="instanceType">The type to activate</param>
/// <param name="parameters">Constructor arguments not provided by the <paramref name="provider"/>.</param>
/// <returns>An activated object of type instanceType</returns>
public static object CreateInstance(IServiceProvider provider, Type instanceType, params object[] parameters)
{
int bestLength = -1;
var seenPreferred = false;
ConstructorMatcher bestMatcher = default;
if (!instanceType.IsAbstract)
{
foreach (var constructor in instanceType.GetConstructors())
{
var matcher = new ConstructorMatcher(constructor);
var isPreferred = constructor.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), false);
var length = matcher.Match(parameters);
if (isPreferred)
{
if (seenPreferred)
{
ThrowMultipleCtorsMarkedWithAttributeException();
}
if (length == -1)
{
ThrowMarkedCtorDoesNotTakeAllProvidedArguments();
}
}
if (isPreferred || bestLength < length)
{
bestLength = length;
bestMatcher = matcher;
}
seenPreferred |= isPreferred;
}
}
if (bestLength == -1)
{
var message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.";
throw new InvalidOperationException(message);
}
return bestMatcher.CreateInstance(provider);
}