注册工厂方法不会阻止Autofac调用ctor

时间:2019-01-09 07:48:03

标签: c# dependency-injection autofac factory-method

我有一个名为ServiceConfiguration的服务,其中有一个非默认的ctor。我正在尝试使用工厂方法通过Autofac注册它:

builder.Register(c=>LoadConfiguration())
       .As<ServiceConfiguration>();

这是简单的LoadConfiguration方法:

private ServiceConfiguration LoadConfiguration() {
    const string fileName = "app.json";
    var json = File.ReadAllText(fileName, Encoding.UTF8);
    var model = JsonConvert.DeserializeObject<ServiceConfiguration>(json);
    return model;
}

我希望当我要求解析LoadConfiguration时,Autofac会呼叫ServiceConfiguration。但似乎正在尝试在ctor上调用ServiceConfiguration。例如。呼叫此行:

var c = container.Resolve<ServiceConfiguration>();

导致此错误:

  

Autofac.Core.DependencyResolutionException:'在执行过程中发生错误   激活特定注册。看到内部异常   有关详细信息。注册:Activator = ServiceConfiguration   (ReflectionActivator),服务= [ServiceConfiguration],生命周期=   Autofac.Core.Lifetime.CurrentScopeLifetime,共享=共享,   所有权= OwnedByLifetimeScope'

而InnerException是:

  

DependencyResolutionException:找不到与   类型上的“ Autofac.Core.Activators.Reflection.DefaultConstructorFinder”   可以使用可用服务来调用“ ServiceConfiguration”,并且   参数:       无法解析构造函数“ Void .ctor(JobsConfiguration)”的参数“ JobsConfiguration作业”。

你能找出我想念的东西吗?

更新: 我没有错过JobsConfiguration的注册。实际上,这不是可注册的类型,我不想注册它。我根本不希望ctor被调用(该服务是从json文件构建的),而是每当有人要求ServiceConfiguration时我都希望Autofac呼叫LoadConfiguration()并使用它返回值。

UPDATE2:

过一会儿,似乎从ServiceConfiguration中提取了一个接口-说IServiceConfiguration-然后注册/解析该接口就可以了。但是我不知道为什么!我的意思是:

builder.Register(c=>LoadConfiguration())
       .As<IServiceConfiguration>();

var c = container.Resolve<IServiceConfiguration>();

有效。但具体版本不行。所以为什么?有什么不同?

1 个答案:

答案 0 :(得分:1)

您应努力将配置文件的加载与对象组合分开。这意味着在调用Resolve时最好 not 加载配置。更改此设置很简单:

ServiceConfiguration configuration = LoadConfiguration();
builder.RegisterInstance(configuration);

也就是说,您指定的注册应该有效:

builder.Register(c => LoadConfiguration())
    .As<ServiceConfiguration>();

与以下相同:

builder.Register(c => LoadConfiguration());

通过此注册,Autofac将自动连接ServiceConfiguration构造函数,但将其留给提供的委托。可能发生了某种情况,您的帖子没有显示。

我使用了以下MCVE(使用Autofav 4.8.1)来验证它是否有效:

class ServiceConfiguration
{
    public ServiceConfiguration(int a, double b) => Console.WriteLine("ctor called.");
}

static ServiceConfiguration LoadConfiguration() => new ServiceConfiguration(2, 6);

static void Main(string[] args)
{
    var builder = new ContainerBuilder();

    builder.Register(_ => LoadConfiguration()).As<ServiceConfiguration>();

    builder.Build().Resolve<ServiceConfiguration>();
}

最后注意:确保ServiceConfiguration不是注入到许多使用者中的应用程序范围的配置类。要了解应用程序范围的配置类有什么问题,请阅读this Q/A