我在使用 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 一起工作。
再次感谢。