简体   繁体   English

Autofac从Container解析构造函数实例?

[英]Autofac Resolve constructor instance from Container?

How can I register a type which takes another type as part of it's constructed without passing an actual instance. 如何在不传递实际实例的情况下注册另一种类型作为其构造的一部分的类型。 Say I have two ISurface types registered. 假设我注册了两个ISurface类型。 I want to register a Car but i don't want to pass in a brand new instance. 我想注册一辆车,但我不想传递一个全新的实例。 I want to use one of the surfaces already defined. 我想使用已经定义的一个表面。

Per the documentation they state : 根据文件,他们说:

  • Autofac sees that IDateWriter maps to TodayWriter so starts creating a TodayWriter. Autofac看到IDateWriter映射到TodayWriter,因此开始创建TodayWriter。
  • Autofac sees that the TodayWriter needs an IOutput in its constructor . Autofac发现TodayWriter在其构造函数中需要IOutput
  • Autofac sees that IOutput maps to ConsoleOutput so creates a new ConsoleOutput instance. Autofac看到IOutput映射到ConsoleOutput,因此创建一个新的ConsoleOutput实例。

Then why must I pass in an instance of Highway when registering a Car? 那么为什么我必须在登记汽车时通过高速公路的实例? Given that I have two Surfaces's registered how do I specify an existing surface? 鉴于我已经注册了两个Surfaces,如何指定现有曲面?

var builder = new ContainerBuilder();
builder.RegisterType<Highway>().Named<ISurface>("Highway");
builder.RegisterType<Ocean>().Named<ISurface>("Ocean");

builder.RegisterType<Car>().Named<IVehicle>("Car").WithParameter("surface", new Highway());

Why do I need to pass a new Highway() ? 为什么我需要通过一个新的Highway()

Here's my models. 这是我的模特。

public interface IVehicle
{
    void Move();
}

public interface ISurface
{
    string SurfaceType { get; }
}

public class Highway : ISurface
{
    public string SurfaceType => "Pavement";
}

public class Ocean : ISurface
{
    public string SurfaceType => "Ocean"
}

public class Car : IVehicle
{
    private ISurface _surface;

    public Car(ISurface surface)
    {
        _surface = surface;
    }

    public void Move()
    {
        Console.WriteLine($"I'm traveling at high speeds across {_surface.SurfaceType}");
    }
}

There's a couple things you can do here: 你可以在这里做几件事:

Option 1 选项1

This keeps in line with what you already have. 这与您已有的一致。 You can still use .WithParameter() but instead pass in a ResolvedParameter instance to explain the parameter to find and how to fulfill the parameter: 您仍然可以使用.WithParameter() ,而是传入ResolvedParameter实例来解释要查找的参数以及如何完成参数:

builder.RegisterType<Car>().Named<IVehicle>( "Car" )
    .WithParameter(
        new ResolvedParameter(
            ( pInfo, ctx ) => pInfo.Name == "surface",
            ( pInfo, ctx ) => ctx.ResolveNamed<ISurface>( "Highway" )
            )
    );

The first delegate passed to the ResolvedParameter constructor provides a way to find the parameter to fulfill, and the second delegate uses the IComponentContext to resolve the Highway instance from the Autofac container. 传递给ResolvedParameter构造函数的第一个委托提供了一种查找要实现的参数的方法,第二个委托使用IComponentContext从Autofac容器中解析Highway实例。

Alternatively there is an overload to WithParameter() that you can use without having to explicitly create a ResolvedParameter : 或者,可以使用WithParameter()的重载,而无需显式创建ResolvedParameter

builder.RegisterType<Car>().Named<IVehicle>( "Car" )
    .WithParameter(
    ( pInfo, ctx ) => pInfo.Name == "surface",
    ( pInfo, ctx ) => ctx.ResolveNamed<ISurface>( "Highway" ) );

Option 2 选项2

This option uses registration with a lambda expression: 此选项使用lambda表达式注册:

builder.Register( ( ctx ) => new Car( ctx.ResolveNamed<ISurface>( "Highway" ) ) ).Named<IVehicle>( "Car" );

Here you can see that I'm passing a lambda that represents my factory function which will again use the IComponentContext to resolve the Highway from the Autofac container. 在这里你可以看到我传递了一个代表我的工厂函数的lambda,它将再次使用IComponentContext从Autofac容器中解析Highway

NOTE 注意

I also read from your question that you wanted the same instance of ISurface each time you requested it. 我还从你的问题中读到,每次你提出要求时,你都想要相同的ISurface实例。 If this is what you want, then you'll need to update your ISurface registrations to include .SingleInstance() : 如果这是你想要的,那么你需要更新你的ISurface注册以包括.SingleInstance()

builder.RegisterType<Highway>().Named<ISurface>( "Highway" ).SingleInstance();
builder.RegisterType<Ocean>().Named<ISurface>( "Ocean" ).SingleInstance();

The default lifetime given to registrations is InstancePerDependency which means that the Autofac resolver will give a new instance of the object every time it is requested. 注册的默认生命周期是InstancePerDependency ,这意味着Autofac解析器将在每次请求时提供对象的新实例。 SingleInstance is essentially a singleton. SingleInstance本质上是一个单例。 You'll only get one instance created and that instance will be returned on every request. 您只会创建一个实例,并且每个请求都会返回该实例。 Here's a link to that info 这是该信息的链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Autofac在构造函数中初始化容器 - Autofac initializing the container in a constructor Autofac通过指定的构造函数解析类 - Autofac resolve class by specified constructor 使用Autofac解析构造函数中的通用IEnumerable - Resolve IEnumerable of a generic in constructor with Autofac 检索Autofac容器以解析服务 - Retrieving Autofac container to resolve services 如何使用参数构造函数动态创建实例,使用autofac DI解决 - How can I create instance Dynamically with parameter constructor resolve using autofac DI 使用autofac解析在运行时在构造函数中使用参数的类实例 - Resolve a class instance which takes parameters in constructor at run time using autofac Autofac 无法解析构造函数“Void”的参数 serviceScopeFactory - Autofac Cannot resolve parameter serviceScopeFactory of constructor 'Void Autofac 使用不同的参数解析相同的 class 实例 - Autofac resolve the same class instance with different parameters 如何从 .NET Core 3.1 中的 Autofac 容器解析已注册的依赖项 - How can I resolve a registered Dependency from an Autofac Container in .NET Core 3.1 当构造函数注入在配置和运行时已知参数时,从AutoFac获取类实例的最佳方法是什么 - What is the best way to get instance of a class from AutoFac when constructor injection has parameters known at configuration and runtime
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM