自动解析容器中的构造函数实例

本文关键字:构造函数 实例 | 更新日期: 2023-09-27 18:12:49

如果不传递实际实例,如何注册一个接受另一个类型作为其构造的一部分的类型?假设我注册了两个表面类型。我想注册一辆车,但我不想传入一个全新的实例。我想用一个已经定义好的曲面。

根据文档他们说:

  • autofacc看到IDateWriter映射到TodayWriter所以开始创建TodayWriter。
  • autofacc看到TodayWriter在它的构造函数
  • Autofac看到IOutput映射到ConsoleOutput,所以创建了一个新的ConsoleOutput实例。

那么为什么我在注册汽车时必须在Highway实例中通过呢?假设我有两个表面注册,我如何指定一个现有的表面?

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

为什么我需要通过新建的高速公路()?

这是我的模型。

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

自动解析容器中的构造函数实例

您可以在这里做几件事:

选项1

这与你已经拥有的保持一致。您仍然可以使用.WithParameter(),但要传递一个ResolvedParameter实例来解释要查找的参数以及如何实现参数:

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

传递给ResolvedParameter构造函数的第一个委托提供了一种找到要实现的参数的方法,第二个委托使用IComponentContext从Autofac容器中解析Highway实例。

或者,您可以使用WithParameter()的重载,而不必显式地创建ResolvedParameter:

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

选项2

该选项使用lambda表达式注册:

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

在这里你可以看到,我正在传递一个lambda,它代表我的工厂函数,它将再次使用IComponentContext来解析来自Autofac容器的Highway

注意

我也从你的问题中读到,你每次请求时都想要相同的ISurface实例。如果这是你想要的,那么你需要更新你的ISurface注册,包括.SingleInstance():

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

注册的默认生存期是InstancePerDependency,这意味着autofacc解析器每次被请求时都会给出一个对象的新实例。SingleInstance本质上是一个单例。您将只创建一个实例,并且该实例将在每次请求时返回。这是info的链接