Autofac从Container解析构造函数实例? [英] Autofac Resolve constructor instance from Container?

查看:186
本文介绍了Autofac从Container解析构造函数实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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. 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.

根据他们声明的文档:

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

那么,为什么在注册汽车时必须经过Highway实例?假设我有两个Surfaces的注册者,如何指定现有的Surface?

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?

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

推荐答案

您可以在此处执行以下操作:

There's a couple things you can do here:

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

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:

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

传递给ResolvedParameter构造函数的第一个委托提供了一种找到要实现的参数的方法,第二个委托使用IComponentContext来从Autofac容器解析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.

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

Alternatively there is an overload to WithParameter() that you can use without having to explicitly create a ResolvedParameter:

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

选项2

此选项使用带有lambda表达式的注册:

Option 2

This option uses registration with a lambda expression:

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

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

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.

我还从您的问题中得知,每次请求ISurface时都需要相同的实例.如果这是您想要的,那么您需要更新您的ISurface注册以包括.SingleInstance():

I also read from your question that you wanted the same instance of ISurface each time you requested it. If this is what you want, then you'll need to update your ISurface registrations to include .SingleInstance() :

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

赋予注册的默认生存期为InstancePerDependency,这意味着Autofac解析器每次请求对象时都会给出该对象的新实例. 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. SingleInstance is essentially a singleton. You'll only get one instance created and that instance will be returned on every request. Here's a link to that info

这篇关于Autofac从Container解析构造函数实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆