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 被释放时调用。

浙公网安备 33010602011771号