首页 > 解决方案 > 尝试创建实例时没有合适的构造函数

问题描述

尝试使用依赖注入设置 .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;

    }

   
}

标签: .netdependency-injection

解决方案


直接从主机的服务提供者解析所需的类型,

//...

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);
}

源代码


推荐阅读