2

我在使用 lightinject 和 .net 核心检索实例时遇到问题。最初这是一组全面的类等,但我已经简化了它。

在我的启动类中, ConfigureServices 方法我有以下代码;

 var container = new ServiceContainer();
 container.Register<IHasEnum, HasEnum>();
 var test = container.GetInstance<IHasEnum>();

第三行产生异常;

System.MissingMethodException
No parameterless constructor defined for this object.

at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, bool publicOnly, bool noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) 
at System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, StackCrawlMark& stackMark) 
at System.Activator.CreateInstance(Type type, bool nonPublic) 
at System.Activator.CreateInstance(Type type) 
at LightInject.<>c.<.ctor>b__20_0(Type type) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 1695 
at LightInject.CompositionRootExecutor.Execute(Type compositionRootType) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 6165 
at LightInject.AssemblyScanner.ExecuteCompositionRoots(IEnumerable<Type> compositionRoots) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 6261 
at LightInject.ServiceContainer.GetEmitMethod(Type serviceType, string serviceName) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3077 
at LightInject.ServiceContainer.GetEmitMethodForDependency(Dependency dependency) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3453 
at LightInject.ServiceContainer.EmitPropertyDependency(IEmitter emitter, PropertyDependency propertyDependency, LocalBuilder instanceVariable) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3432
at LightInject.ServiceContainer.EmitPropertyDependencies(ConstructionInfo constructionInfo, IEmitter emitter) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3515 
at LightInject.ServiceContainer.EmitNewInstanceUsingImplementingType(IEmitter emitter, ConstructionInfo constructionInfo, Action<IEmitter> decoratorTargetEmitMethod) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3346
at LightInject.ServiceContainer.EmitNewInstance(ServiceRegistration serviceRegistration, IEmitter emitter) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3301 
at LightInject.<>c__DisplayClass147_0.<CreateEmitMethodWrapper>b__0(IEmitter ms) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3122 
at LightInject.ServiceContainer.CreateDynamicMethodDelegate(Action<IEmitter> serviceEmitter) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3044 
at LightInject.ServiceContainer.CreateDelegate(Type serviceType, string serviceName, bool throwError) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3909 
at LightInject.ServiceContainer.CreateDefaultDelegate(Type serviceType, bool throwError) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 3872 
at LightInject.ServiceContainer.GetInstance(Type serviceType) in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 2541 
at LightInject.ServiceContainer.GetInstance<TService>() in C:\projects\lightinject\build\tmp\netstandard13\Binary\LightInject\LightInject.cs:line 2591 

有问题的类 HasEnum 在这里;

public class HasEnum : IHasEnum
{
    private Colours _colours;

    public Colours PickedColour
    {
        get
        {
            return _colours;

        }
        internal set { _colours = Colours.Red; }
    }
}

根据异常的建议,我向 HasEnum 添加了一个默认构造函数,结果相同。非常令人抓狂的是,当我在一个单独的(高度简化的)项目中尝试这个时,它似乎工作正常。我已经检查了两个项目中 lightinject 的版本并且它们匹配。我是否在不知不觉中设置了某种设置?

非常感谢

编辑 - 奇怪的是,如果我从 PickedColour 属性中删除设置器,则不会发生此错误。

public Colours PickedColour
{
    get { return _colours; }
}

所以这似乎与这个枚举属性上的设置器有关。即使我放置了一个空白集{},这个异常也会抛出。

编辑 2:IHasEnum 接口;

public interface IHasEnum
{
    Colours PickedColour { get; }
}

编辑3:感谢您的回复。在 .net 核心中使用 lightinject 方面,没有大量的文档。.net 核心特定版本告诉您像这样使用它:http ://www.lightinject.net/microsoft.dependencyinjection/

我遵循了这一点,我的测试类的错误仍然存​​在。如果我通过删除枚举类型来简化测试类,它就可以正常工作。

为了进一步明确我是如何注册服务的,下面是跨多个文件和类的相关片段;

// The startup method creates the config
public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json")
                .AddEnvironmentVariables();
    builder.AddInMemoryCollection();
    Configuration = builder.Build();
}

// The configure method passes The configuration to a new 
// application object - this is what creates the lightinject container
public IServiceProvider ConfigureServices(IServiceCollection services)
{       
    services.AddSingleton(Configuration);
    var app = new PocApplication(Configuration); // the main section of PocApplication is below this method

    var service = services.AddPocCore(app); // This extension method is listed below, is in another file. 


    return service;
}

// This method creates the ServiceContainer
public PocApplication(IConfiguration config)
{
    var container = new ServiceContainer();

    Container = container;
    // Other items are omitted, the ServiceContainer 
    // is passed back.      
}


public static IServiceProvider AddPocCore(this IServiceCollection services, PocApplication pocApplication)
{
    var pocContainer = pocApplication.Container;        

    pocContainer.Register<IHasEnum, HasEnum>();
    // other services registered here

    return services.WrapAspNetContainer(pocApplication.Container); // another extension, shown below. 
}

public static IServiceProvider WrapAspNetContainer(this IServiceCollection services, IServiceContainer container)
{
    return container.CreateServiceProvider(services); 
    // This is the way to use lightinject to replace the container with the custom
    // one as per the documentation. 
}

除了相关部分之外,我已经删除了所有内容。当执行到达主控制器并且我尝试获取 IHasEnum 实现时,同样的异常结果。我已经按照文档使用了注册,不知道如何让它工作。

非常感谢。

编辑4:

我已经缩小了错误的来源 - 但不明白为什么会发生。IHasEnum 的实现是一个红鲱鱼 - 它正在正确注册。我找到了一个实现 ICompsitionRoot 的类——一旦我删除了这个用法,就会检索 HasEnum 实例。根据 lightInject 文档(http://www.lightinject.net/#composition-root),任何实现 ICompositionRoot 的类都将在设置 DI 时执行。实现此接口的组合类对于从 appsettings.json 文件构造设置对象是必要的。

为了证明这一点,我将再次展示 AddPocCore 方法,添加的行带有对构成 Configuration 组合 Root 的扩展方法的调用;

public static IServiceProvider AddPocCore(this IServiceCollection services, PocApplication pocApplication)
{
    var pocContainer = pocApplication.Container;        

    pocContainer.Register<IHasEnum, HasEnum>();        

    // The registerfrom extension method - shown below. 
    container.RegisterFrom(new ConfigurationCompositionRoot(application.Configuration));


    return services.WrapAspNetContainer(pocApplication.Container); // another extension, shown below. 
}


public static void RegisterFrom<TCompositionRoot>(this IServiceRegistry container, TCompositionRoot instance)
    where TCompositionRoot : ICompositionRoot
{
    // this is where the compose method is called. 
    instance.Compose(container);
}


// Either removing ICompositionRoot inheritance or the constructor means the error doesn't occur 
public sealed class ConfigurationCompositionRoot : ICompositionRoot
{
    private readonly IConfiguration _config;

    public ConfigurationCompositionRoot(IConfiguration config)
    {
        // I think this is where the default constructor exception method is
        // being generated, debugging shows the config object is instantiated here. 
        _config = config;
    }
    public void Compose(IServiceRegistry container)
    {
       // This is where the config is used to create the settings objects
       // which includes the database connection string. 
    }
}

所以本质上,只要我删除对扩展方法的调用,然后在 ConfigurationCompositionRoot 中,我从类声明中删除 ICompositionRoot(阻止 lightinject 拦截它),程序就会按预期工作。我只是不明白如何在启动时使用此组合根将我的设置放入对象中。整个事情变得相当长,对此感到抱歉 - 只是真的想让它与 dot net core 一起工作。

再次感谢。

4

0 回答 0