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

时间:2016-10-11 20:17:30

标签: c# dependency-injection autofac

如何在不传递实际实例的情况下注册另一种类型的类型作为其构造的一部分。假设我注册了两个ISurface类型。我想注册一辆车,但我不想传递一个全新的实例。我想使用已经定义的一个表面。

根据他们所说的文件:

  • Autofac发现IDateWriter映射到TodayWriter,因此开始创建 一个TodayWriter。
  • Autofac发现TodayWriter需要一个IOutput 构造即可。
  • Autofac发现IOutput映射到ConsoleOutput,因此创建了一个新的 ConsoleOutput实例。

那么为什么我必须在登记汽车时通过高速公路的实例?鉴于我已经注册了两个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());

为什么我需要传递新的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 个答案:

答案 0 :(得分:6)

你可以在这里做几件事:

选项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,这意味着每次请求时,Autofac解析器都会提供该对象的新实例。 SingleInstance本质上是一个单身人士。您只会创建一个实例,并且每次请求都会返回该实例。这是该信息的link