Golang反射による依存注入
3278 ワード
Golang反射による依存注入
Coding/Golang #Golang #Golang/reflect
依存注入
本人は
構想注入対象オブジェクトを含むインスタンスを作成し、Map を格納する.は、他のオブジェクトに注入する必要があるオブジェクトインスタンスを作成し、このMap にも格納する.オブジェクト登録が完了すると、Injectメソッドが呼び出され、InjectはMap全体を遍歴し、オブジェクト内のすべての注入する属性を探し出し、 に注入する.
構造体改造前のコード
構造体改造後のコード
インプリメンテーション
Tag
Tag
はんしゃちゅうにゅう
ここでPublicプロパティの値を変更するのは簡単です.
しかし、値がPrivateである場合、Setを呼び出すとPanicが発生し、メソッド
これらはすべて標準ライブラリの中の方法で、派手なものは存在しません.
ふろく
Coding/Golang #Golang #Golang/reflect
依存注入
本人は
Java
がGolang
に転入するとJavaの思考を持ち込むので、注入に依存するのは良いもので、概念はあまり述べません.構想
構造体改造前のコード
func main(){
runner := &Runner{}
eater := &Eater{}
people := NewPeople(runner, eater)
people.Run.Run()
}
func NewPeople(run IRun, eat IEat) IPeople {
return & People{
Run: run,
Eat: eat,
}
}
type People struct {
Run IRun
Eat IEat
}
構造体改造後のコード
func main(){
core.register("run", &Runner{}) // run Runner
core.register("eat", &Eater{}) // eat Eater
people := &People{}
core.autoRegister(people) // *main.People People
core.inject() // Tag:"auto"
people.Run.Run()
}
type People struct {
Run IRun `auto:"run"`
Eat IEat `auto:"eat"`
}
インプリメンテーション
Tag
Tag
auto
を使用して、run名で登録されたオブジェクトを取り出して注入するなど、自動注入が必要なオブジェクトをマークします.フィールドを巡回して、すべてのTagがauto:"run"
のフィールドを見つけます.value := reflect.ValueOf(obj)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
for i := 0; i < value.NumField(); i++ {
name := value.Type().Field(i).Tag.Get("auto")
// tag auto
}
はんしゃちゅうにゅう
ここでPublicプロパティの値を変更するのは簡単です.
field := value.Field(i) //
field.Set(value) //
しかし、値がPrivateである場合、Setを呼び出すとPanicが発生し、メソッド
auto
を使用して、主な問題がPrivateオブジェクトに値を設定する方法であるかを判断することができます.field := value.Field(i)
field = reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem()
field.Set(value)
これらはすべて標準ライブラリの中の方法で、派手なものは存在しません.
ふろく
import (
"fmt"
"reflect"
"unsafe"
)
const (
InjectorTag = "auto"
)
var objs map[string]reflect.Value
func init() {
objs = make(map[string]reflect.Value, 10)
}
// Register
func Register(name string, v interface{}) {
objs[name] = reflect.ValueOf(v)
}
// AutoRegister
func AutoRegister(v interface{}) {
rv := reflect.ValueOf(v)
Register(rv.Type().String(), rv)
}
// Get
func Get(key string) interface{} {
v, ok := objs[key]
if ok {
return v.Interface()
}
return nil
}
// Remove
func Remove(key string) {
delete(objs, key)
}
func Inject() {
for _, v := range objs {
value := v
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
for i := 0; i < value.NumField(); i++ {
name := value.Type().Field(i).Tag.Get(InjectorTag)
temp, ok := objs[name]
if ok {
field := value.Field(i)
if field.CanSet() {
field.Set(temp)
} else {
field = reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem()
field.Set(temp)
}
}
}
}
}