Compare commits

1 Commits

Author SHA1 Message Date
des
a90823eba4 自动查找实现
Some checks failed
Wire Tests / build (1.25.x, macos-latest) (push) Has been cancelled
Wire Tests / build (1.25.x, ubuntu-latest) (push) Has been cancelled
Wire Tests / build (1.25.x, windows-latest) (push) Has been cancelled
但是自动收集到数组是个超级糟糕的需求。糟糕到我认为需要另起炉灶。
2026-02-24 20:55:18 +08:00
2 changed files with 35 additions and 2 deletions

View File

@@ -329,6 +329,8 @@ func verifyArgsUsed(set *ProviderSet, used []*providerSetSrc) []error {
// buildProviderMap creates the providerMap and srcMap fields for a given // buildProviderMap creates the providerMap and srcMap fields for a given
// provider set. The given provider set's providerMap and srcMap fields are // provider set. The given provider set's providerMap and srcMap fields are
// ignored. // ignored.
//
// 这里就是查找注入的核心
func buildProviderMap(fset *token.FileSet, hasher typeutil.Hasher, set *ProviderSet) (*typeutil.Map, *typeutil.Map, []error) { func buildProviderMap(fset *token.FileSet, hasher typeutil.Hasher, set *ProviderSet) (*typeutil.Map, *typeutil.Map, []error) {
providerMap := new(typeutil.Map) providerMap := new(typeutil.Map)
providerMap.SetHasher(hasher) providerMap.SetHasher(hasher)

View File

@@ -74,6 +74,7 @@ func (p *providerSetSrc) description(fset *token.FileSet, typ types.Type) string
// trace returns a slice of strings describing the (possibly recursive) source // trace returns a slice of strings describing the (possibly recursive) source
// of p, including line numbers. // of p, including line numbers.
// 这里是 srcMap 唯一使用的地方,看起来似乎只是用作错误输出,应该不会干扰我的修改。
func (p *providerSetSrc) trace(fset *token.FileSet, typ types.Type) []string { func (p *providerSetSrc) trace(fset *token.FileSet, typ types.Type) []string {
var retval []string var retval []string
// Only Imports need recursion. // Only Imports need recursion.
@@ -122,12 +123,39 @@ func (set *ProviderSet) Outputs() []types.Type {
} }
// For returns a ProvidedType for the given type, or the zero ProvidedType. // For returns a ProvidedType for the given type, or the zero ProvidedType.
// 这个方法是我们改造的重点,两个功能都要从这个函数进行动作
// - 自动查找所有接口的实现
//
// 已知的困难是
//
// 比如遇见一个新的接口,遍历所有 ProvidedType 进行检查并向 ProviderMap 中添加项以避免下次检查。
// 但是如果有两个接口先后需要查找,此时第二次查找同样会遍历第一次查找生成的 ProviderType 数据。
// 我想起来了,好像 ProviderSet 中有个 providers 属性储存了原始的那啥。可以使用这个遍历避免 ProviderType 膨胀问题
func (set *ProviderSet) For(t types.Type) ProvidedType { func (set *ProviderSet) For(t types.Type) ProvidedType {
pt := set.providerMap.At(t) pt := set.providerMap.At(t)
if pt == nil { if pt != nil {
return *pt.(*ProvidedType)
}
face, isFace := t.Underlying().(*types.Interface)
if !isFace {
return ProvidedType{} return ProvidedType{}
} }
return *pt.(*ProvidedType) var addMap []ProvidedType
for _, provider := range set.Providers {
pro := types.Implements(provider.Out[0], face)
if pro {
addMap = append(addMap, ProvidedType{t: t, p: provider})
}
}
if len(addMap) == 0 {
return ProvidedType{}
} else if len(addMap) == 1 {
provider := addMap[0]
set.providerMap.Set(t, &provider)
set.srcMap.Set(t, &providerSetSrc{Provider: provider.p})
return provider
}
panic("接口 " + t.String() + " 拥有多个实现")
} }
// An IfaceBinding declares that a type should be used to satisfy inputs // An IfaceBinding declares that a type should be used to satisfy inputs
@@ -1155,6 +1183,9 @@ func isProviderSetType(t types.Type) bool {
// can be a *Provider (a provider function), a *Value (wire.Value), or an // can be a *Provider (a provider function), a *Value (wire.Value), or an
// *InjectorArgs (arguments to the injector function). The zero value has // *InjectorArgs (arguments to the injector function). The zero value has
// none of the above, and returns true for IsNil. // none of the above, and returns true for IsNil.
//
// 在我的角度来看,这东西其实有点职责混淆。因为他还顺带兼任了判断类是否存在的功能。
// 总之,这个结构体标记了提供者,还有一个检查是否有提供者的方法。当然,可能不止这一个功能。
type ProvidedType struct { type ProvidedType struct {
// t is the provided concrete type. // t is the provided concrete type.
t types.Type t types.Type