I have code
var t reflect.Type = LaunchController(route.controller)
// create controller ptr .
var appControllerPtr reflect.Value = reflect.New(t)
fmt.Println(appControllerPtr) //#=> <**controller.AppController Value>
var appController reflect.Value = appControllerPtr.Elem()
// Create and configure base controller
var c *Controller = &Controller{
Request: r,
Writer: w,
Name: t.Name(),
}
//this should assign *goninja.Controller field in application controllers
var controllerField reflect.Value = reflect.ValueOf(appController).Field(0)
controllerField.Elem().Set(reflect.ValueOf(c))
This creates pointer to element, and afterwards trying to assign value, into 0 field of this struct.
My struct, that i'm trying to reflect looks like
type AppController struct {
*goninja.Controller
}
However when I'm trying to assign this field with code
controllerField.Elem().Set(reflect.ValueOf(c))
I'm facing following error
reflect: reflect.Value.Set using value obtained using unexported field
What am i doin wrong? Also I cant understand why my reflect.New(t) returns reflect.Value with 2 asterisks in beginning **
You don't give your complete code, so I have to guess a bit, but I suspect that the Controller field of the AppController structure has a lower-case name. Right? Here is my attempt to produce a minimal example from your code: working (with upper-case field name) and non-working (with lower-case fieldname).
Also: where you write reflect.ValueOf(appController).Field(0), the appController is already of type reflect.Value, so the ValueOf is not required. You can just write appController.Field(0) as in the example code I linked above.
Related
I am using gorm package (https://github.com/jinzhu/gorm) as my database library in golang. I have many classes (database tables) like "Hotel" or "Package". Duplicating code is not good programming practice. As a silly example - lets assume I want to get first object from each table. I can write this method (GetFirstHotel, GetFirstPackage...) for each object. But better way would be to have just a single method GetFirstItem, where I would use first param to create object with same class as parameter, then pass it to gorm, which will fill it with data from database, then return it as interface{}. I tried to use reflect for that, but failed, because I probably don't understand it much.
Maybe I just didn't discover some function in gorm library, or I can't use reflect package properly. How should I implement GetFirstItem function. Is it possible to have this implemented, or should I rather repeat my code?
package main
import (
"github.com/jinzhu/gorm"
)
var db gorm.DB
type Hotel struct {
ID int64
Name string
Lat float64
Lon float64
}
type Package struct {
ID int64
Name string
Text string
}
func GetFirstHotel() (hotel Hotel) {
db.First(&hotel)
}
func GetFirstPackage() (pack Package) {
db.First(&pack)
}
func main() {
var firstHotel, firstPackage interface{}
//first method
firstHotel = GetFirstHotel()
firstPackage = GetFirstPackage()
//method i want to use
firstHotel = GetFirstItem(Hotel{})
firstPackage = GetFirstItem(Package{})
}
func GetFirstItem(item interface{}) interface{} {
//how to implement this?
//probably with some use of reflect package
}
The db.First method returns db reference and hydrates the row into the passed structure.
The closest to your desired method is
func GetFirstItem(item interface{}) error {
return db.First(item).Error
}
This simply requires you keep a reference to the parameter
var firstHotel &Hotel{}
err := GetFirstItem(firstHotel)
Returning the hydrated object for all types would required type parameters (generics). I think you'll find the current situation is workable within limits.
see also: Why no generics in Go?
I'm trying to set up a class that has a dictionary with an int and my own object. On init I do not have anything to put in this dictionary.
class Menu
{
var emptyDic = Dictionary<String, String>()
var menuItem: Dictionary<Int,MenuItem>()
init()
{
//init object code
}
}
The emptyDic variable (which I got from StackOverflow) works fine, but I get an error consecutive declarations on a line must be separated by a ; if I mirror the same syntax for my menuItem dictionary. If I remove the () it complains that self.menuItem is not initialised.
I've not seen much written about dictionaries with other types other than strings. Is this a case for making it an optional or am I missing something more obvious?
Thanks
Andrew
You didn't copy the syntax. ':' and '=' are not equivalent. In this case, one specifies a type while the other specifies initialization.
Try:
var menuItem = Dictionary<Int,MenuItem>()
Consider the following code:
class Foo(var name: String = "bar")
Now i try to get the value and the correct type of it via reflection:
val foo = new Foo
val field = foo.getClass.getDeclaredField("name")
field.setAccessible(true)
//This is where it doesn't work
val value = field.get(????)
I tried things like field.get(foo), but that just returns an java.lang.Object but no String. Basically I need the correct type, because I want to invoke a method on it (e. g. toCharArray).
What is the suggested way to do that?
As others have mentioned, the reflection methods return Object so you have to cast. You may be better using the method that the Scala compiler creates for field access rather than having to change the visibility of the private field. (I'm not even sure if the name private field is guaranteed to be the same as that of the accessor methods.)
val foo = new Foo
val method = foo.getClass.getDeclaredMethod("name")
val value = method.get(foo).asInstanceOf[String]
getDeclaredField is a method of java.lang.Class.
You have to change foo.getDeclaredField("name") to foo.getClass.getDeclaredField("name") (or classOf[Foo].getDeclaredField("name")) to get the field.
You can get the type with getType method in class Field but it won't help you because it returns Class[_]. Given than you know that the type is a String you can always cast the value returned using field.get(foo).asInstanceOf[String]
AFAIK, reflection always work with Object, and you have to cast the results yourself.
This is how one can get list of fieldnames and its value of a case class:
First, using reflection, get fields info as follows -
val TUPLE2_OF_FIELDNAME_TO_GETTERS = typeOf[<CLASS>].members
.filter(!_.isMethod)
.map(x => (x.name.toString, classOf[<CLASS>].getDeclaredMethod(x.name.toString.trim)))
How to use it?
getFieldNameAndValue(obj: <CLASS>): Seq[(String, String)] {
var output = Seq[(String, String)]()
for(fieldToGetter <- TUPLE2_OF_FIELDNAME_TO_GETTERS) {
val fieldNameAsString = fieldToGetter._1
val getter = fieldToGetter._2
val fieldValue = getter.invoke(obj).toString
output += (fieldName, fieldValue)
}
}
foo.getClass.getDeclaredField("name").getString(foo)
should work if you want to avoid asInstanceOf. get* is available for various types
I am a Java programmer and need to work on a Flex/ActionScript project right now. I got an example of using ITreeDataDesriptor from Flex 3 Cookbook, but there is one line of actionscript code that's hard for me to understand. I appreciate if someone could explain this a little further.
public function getData(node:Object, model:Object=null):Object
{
if (node is Office) {
return {children:{label:node.name, label:node.address}};
}
}
The part that I didn't understand was "{children:{label:node.name, label:node.address}}". Office is simply a value object that contains two String properties: name and address.
The following return expression (modified from the question) ...
return {children:{label:node.name, body:node.address}}
... is functionally equivalent to this code ...
var obj:Object = new Object();
obj.children = new Object();
obj.children.label = node.name;
obj.children.body = node.address;
return obj;
The anonymous object returned in the question code complicates matters because it defines a property twice. In that case, the first declaration is used, and the subsequent one(s) are ignored. No compile-time or runtime error is thrown.
I think in Java you would call that a map or an associative array. In Javascript and Actionscript you can say this to create an object with certain properties:
var myobject = {
'prop1': 100,
'prop2': {
'a': 1
}
}
trace( myobject.prop1 ); // 100
trace( myobject.prop2.a ); // 1
In your example it's just returned as a nameless object.
return {children:{label:node.name, label:node.address}};
Means you are returning a new Object. The {} are the Object's constructor, and in this case its an Anonymous object.
Thank you both for the quick response. So if I understand your explanations correctly, the return statement is returning an anonymous object, and this object has only one property named "children", which is again an associative array - ok, here is the part I don't quite understand still, it seems that both properties in this array are named "label", is this allowed?
Data binding in ActionScript is really cool. But what if I want to refactor a big switch or if statement inside the curly braces into a function, for example:
{person.gender == 'male' ? 'Mr.' : 'Ms.'}
into:
{salutation(person)}
The compiler doesn't let me do that. I know about properties and I could write getters and setters on the person object. But since I am using inlined JSON objects now that's not convenient(I think). What are other good ways to refactor this code?
To answer Matt's comment. The data type of person is just plain Object. It was decoded from JSON format coming from a service call.
You'll need to make the Person class (assuming you have one) bindable in order for this to work.
However, since you are saying you're using JSON objects, I'm assuming you just have anonymous objects that were parsed from a JSON string. In that case, I'm pretty sure that won't work. You'll need to create a strongly typed object that has bindable properties.
Just FYI: to avoid having to write custom JSON parsers for every object you want to create, you can create strong typed objects from vanilla objects using a bytearray trick:
public static function toInstance( object:Object, clazz:Class ):* {
var bytes:ByteArray = new ByteArray();
bytes.objectEncoding = ObjectEncoding.AMF0;
// Find the objects and byetArray.writeObject them, adding in the
// class configuration variable name -- essentially, we're constructing
// and AMF packet here that contains the class information so that
// we can simplly byteArray.readObject the sucker for the translation
// Write out the bytes of the original object
var objBytes:ByteArray = new ByteArray();
objBytes.objectEncoding = ObjectEncoding.AMF0;
objBytes.writeObject( object );
// Register all of the classes so they can be decoded via AMF
var typeInfo:XML = describeType( clazz );
var fullyQualifiedName:String = typeInfo.#name.toString().replace( /::/, "." );
registerClassAlias( fullyQualifiedName, clazz );
// Write the new object information starting with the class information
var len:int = fullyQualifiedName.length;
bytes.writeByte( 0x10 ); // 0x10 is AMF0 for "typed object (class instance)"
bytes.writeUTF( fullyQualifiedName );
// After the class name is set up, write the rest of the object
bytes.writeBytes( objBytes, 1 );
// Read in the object with the class property added and return that
bytes.position = 0;
// This generates some ReferenceErrors of the object being passed in
// has properties that aren't in the class instance, and generates TypeErrors
// when property values cannot be converted to correct values (such as false
// being the value, when it needs to be a Date instead). However, these
// errors are not thrown at runtime (and only appear in trace ouput when
// debugging), so a try/catch block isn't necessary. I'm not sure if this
// classifies as a bug or not... but I wanted to explain why if you debug
// you might seem some TypeError or ReferenceError items appear.
var result:* = bytes.readObject();
return result;
}