Skip to content

Instantly share code, notes, and snippets.

@ogerardin
Created February 25, 2019 11:43
Show Gist options
  • Save ogerardin/5aa272f69563475ba9d7b3194b12ae57 to your computer and use it in GitHub Desktop.
Save ogerardin/5aa272f69563475ba9d7b3194b12ae57 to your computer and use it in GitHub Desktop.
package poly
import (
"b2b-go/lib/typeregistry"
"fmt"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"github.com/globalsign/mgo/dbtest"
"io/ioutil"
"os"
"reflect"
"testing"
)
type I interface {
f1()
}
type S1 struct {
X int
}
type S2 struct {
S1
Y int
}
func (*S1) f1() {
fmt.Println("f1")
}
/*func (*S2) f1() {
fmt.Println("S2")
}
*/
type Wrapper struct {
Id bson.ObjectId `bson:"_id"`
TypeKey string
Val interface{}
}
func save(coll *mgo.Collection, s I) (bson.ObjectId, error) {
t := reflect.TypeOf(s)
wrapper := Wrapper{
Id: bson.NewObjectId(),
TypeKey: typeregistry.GetKey(t),
Val: s,
}
return wrapper.Id, coll.Insert(wrapper)
}
func getById(coll *mgo.Collection, id interface{}) (*I, error) {
// read wrapper
wrapper := Wrapper{}
err := coll.Find(bson.M{"_id": id}).One(&wrapper)
if err != nil {
return nil, err
}
// obtain Type from registry
t := typeregistry.GetType(wrapper.TypeKey)
// get a pointer to a new value of this type
pt := reflect.New(t)
// FIXME populate value using wrapper.Val (type bson.M)
/*
m := wrapper.Val.(bson.M)
bsonBytes, _ := bson.Marshal(m)
bson.Unmarshal(bsonBytes, pt)
*/
// return the value as *I
i := pt.Elem().Interface().(I)
return &i, nil
}
func TestPoly(t *testing.T) {
d, _ := ioutil.TempDir(os.TempDir(), "mongotools-test")
server := dbtest.DBServer{}
server.SetPath(d)
//server.SetPort(27017)
defer server.Stop()
session := server.Session()
defer session.Close()
coll := session.DB("").C("polytest")
saveAndRetrieve(coll, t)
//time.Sleep(time.Hour)
}
func saveAndRetrieve(coll *mgo.Collection, t *testing.T) {
typeregistry.Register(reflect.TypeOf((*S1)(nil)).Elem())
typeregistry.Register(reflect.TypeOf((*S2)(nil)).Elem())
s1 := S1{
1,
}
s2 := S2{
S1{
2,
},
3,
}
id1, _ := save(coll, &s1)
t.Logf("object 1 saved %v", id1)
id2, _ := save(coll, &s2)
t.Logf("object 2 saved %v", id2)
r1, _ := getById(coll, id1)
t.Logf("object 1 retrieved %v", r1)
r2, _ := getById(coll, id2)
t.Logf("object 2 retrieved %v", r2)
}
package typeregistry
import "reflect"
var types map[string]reflect.Type
func init() {
types = make(map[string]reflect.Type)
}
func Register(t reflect.Type) {
key := GetKey(t)
types[key] = t
}
func GetKey(t reflect.Type) string {
key := t.PkgPath() + "." + t.Name()
return key
}
func GetType(key string) reflect.Type {
t := types[key]
return t
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment