VContainer-registering/register-factory | 注册——注册工厂
VContainer 通常在被首次解析时才构建依赖对象(注册实例 除外)。如需精细控制依赖创建时机,可注册工厂方法。
工厂方法本质是 Func<>
委托,可像普通依赖一样被解析。用于在任意时刻创建对象。
:::note
虽然叫"工厂",但实际可以返回已存在的对象。这在需要为同类型配置不同实例时很有用,例如为本地多人游戏中每个玩家创建独立控制器。
:::
以下示例中依赖解析仅发生一次。在 Create()
方法中不会自动触发解析(这是构造函数的工作),但可通过 IObjectResolver
API 手动解析。
class FooFactory
{
public FooFactory(DependencyA dependencyA)
{
this.dependencyA = dependencyA;
}
public Foo Create(int b) => new Foo(b, dependencyA);
}
builder.Register<FooFactory>(Lifetime.Singleton); // 注册
// ...
var factory = container.Resolve<FooFactory>(); // 触发依赖解析
// ...
var foo1 = factory.Create(1); // 无需解析
var foo2 = factory.Create(2); // 无需解析
var foo3 = factory.Create(3); // 无需解析
对于简单场景,可直接用 lambda 表达式 进行注册。
:::caution
VContainer 不会自动管理工厂返回对象的生命周期。若工厂返回可销毁对象(即实现了 IDisposable 接口的对象),需自行处理。此时推荐使用工厂类,因为工厂本身会被 VContainer 管理并自动销毁(若实现 IDisposable
)。
:::
注册仅在运行时需要参数的 Func<>
工厂
无其他依赖的工厂可这样注册:
builder.RegisterFactory<int, Foo>(x => new Foo(x));
使用方法如下:
class ClassA
{
readonly Func<int, Foo> factory;
public ClassA(Func<int, Foo> factory)
{
this.factory = factory;
}
public void DoSomething()
{
var foo = factory(100);
// ...
}
}
注册需要容器依赖的 Func<>
工厂
如果工厂方法确实需要其他依赖项,则需要为其提供 IObjectResolver
。为此,可以注册一个 Func<>
, 该Func<>
接受一个 IObjectResolver
并返回实际想要使用的的 Func<>
。
builder.RegisterFactory<int, Foo>(container => // container 是一个 IObjectResolver
{
var dependency = container.Resolve<Dependency>(); // 一个作用域内对应一次解析
return x => new Foo(x, dependency); // 每次调用工厂时执行
}, Lifetime.Scoped);
此方式需要 Lifetime
参数来指定内部 Func<>
生成的频率,即外部 Func<>
被调用的频率。
使用方式与简单工厂一致:
class ClassA
{
readonly Func<int, Foo> factory;
public ClassA(Func<int, Foo> factory)
{
this.factory = factory;
}
public void DoSomething()
{
var foo = factory.Invoke(100);
// ...
}
}
IObjectResolver
的扩展方法在工厂中很有用:
builder.RegisterFactory<CharacterType, CharacterActor>(container =>
{
return characterType =>
{
var characterPrefab = ...
return container.Instantiate(characterPrefab, parentTransform);
}
}, Lifetime.Scoped);
更多信息参阅 容器 API。
:::note
使用 lambda 函数进行 Func<>
注册是常见情况的简写。在复杂场景中,考虑定义并注册自己的工厂类。
:::
注册工厂方法
工厂可以注册为任何可以转换为 Func<>
的委托,包括类方法。这样,无论底层实现多么复杂,所有工厂都可以作为 Func<>
使用。以下是实现方式。
假设有这个类...
class FooFactory
{
public FooFactory(DependencyA dependencyA)
{
this.dependencyA = dependencyA;
}
public Foo Create(int b) => new Foo(b, dependencyA);
}
以下可以使用 FooFactory
作为 Func<>
处理,而无需了解或关心完整的类。
builder.Register<FooFactory>(Lifetime.Singleton);
builder.RegisterFactory(container => container.Resolve<FooFactory>().Create, Lifetime.Singleton);
// ...
var factory = container.Resolve<Func<int, Foo>>();
var foo1 = factory(1);
var foo2 = factory(2);
var foo3 = factory(3);
var originalFactoryObject = container.Resolve<FooFactory>(); // 如果需要,工厂对象仍然存在。
// 如果 FooFactory 实现了 IDisposable,那么它将在 IObjectResolver 被释放时调用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~