自动查找实现
但是自动收集到数组是个超级糟糕的需求。糟糕到我认为需要另起炉灶。
This commit is contained in:
@@ -329,6 +329,8 @@ func verifyArgsUsed(set *ProviderSet, used []*providerSetSrc) []error {
|
||||
// buildProviderMap creates the providerMap and srcMap fields for a given
|
||||
// provider set. The given provider set's providerMap and srcMap fields are
|
||||
// ignored.
|
||||
//
|
||||
// 这里就是查找注入的核心
|
||||
func buildProviderMap(fset *token.FileSet, hasher typeutil.Hasher, set *ProviderSet) (*typeutil.Map, *typeutil.Map, []error) {
|
||||
providerMap := new(typeutil.Map)
|
||||
providerMap.SetHasher(hasher)
|
||||
|
||||
@@ -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
|
||||
// of p, including line numbers.
|
||||
// 这里是 srcMap 唯一使用的地方,看起来似乎只是用作错误输出,应该不会干扰我的修改。
|
||||
func (p *providerSetSrc) trace(fset *token.FileSet, typ types.Type) []string {
|
||||
var retval []string
|
||||
// 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.
|
||||
// 这个方法是我们改造的重点,两个功能都要从这个函数进行动作
|
||||
// - 自动查找所有接口的实现
|
||||
//
|
||||
// 已知的困难是
|
||||
//
|
||||
// 比如遇见一个新的接口,遍历所有 ProvidedType 进行检查并向 ProviderMap 中添加项以避免下次检查。
|
||||
// 但是如果有两个接口先后需要查找,此时第二次查找同样会遍历第一次查找生成的 ProviderType 数据。
|
||||
// 我想起来了,好像 ProviderSet 中有个 providers 属性储存了原始的那啥。可以使用这个遍历避免 ProviderType 膨胀问题
|
||||
func (set *ProviderSet) For(t types.Type) ProvidedType {
|
||||
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 *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
|
||||
@@ -1155,6 +1183,9 @@ func isProviderSetType(t types.Type) bool {
|
||||
// can be a *Provider (a provider function), a *Value (wire.Value), or an
|
||||
// *InjectorArgs (arguments to the injector function). The zero value has
|
||||
// none of the above, and returns true for IsNil.
|
||||
//
|
||||
// 在我的角度来看,这东西其实有点职责混淆。因为他还顺带兼任了判断类是否存在的功能。
|
||||
// 总之,这个结构体标记了提供者,还有一个检查是否有提供者的方法。当然,可能不止这一个功能。
|
||||
type ProvidedType struct {
|
||||
// t is the provided concrete type.
|
||||
t types.Type
|
||||
|
||||
Reference in New Issue
Block a user