自动查找实现
但是自动收集到数组是个超级糟糕的需求。糟糕到我认为需要另起炉灶。
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
|
// 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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user