I have a path for an object within an object within an object and I want to set it using Groovy's dynamic abilities. Usually you can do so just by doing the following:
class Foo {
String bar
}
Foo foo = new Foo
foo."bar" = 'foobar'
That works OK. But what if you have nested objects? Something like:
class Foo {
Bar bar
}
class Bar {
String setMe
}
Now I want to use the dynamic setting, but
Foo foo = new Foo()
foo."bar.setMe" = 'This is the string I set into Bar'
Returns a MissingFieldException.
Any hints?
UPDATE: Thanks to Tim for pointing me in the right direction, the initial code on there works great at retrieving a property, but I need to set the value using the path string.
Here's what I came up with from the page Tim suggested:
def getProperty(object, String propertyPath) {
propertyPath.tokenize('.').inject object, {obj, prop ->
obj[prop]
}
}
void setProperty(Object object, String propertyPath, Object value) {
def pathElements = propertyPath.tokenize('.')
Object parent = getProperty(object, pathElements[0..-2].join('.'))
parent[pathElements[-1]] = value
}
Following works correctly.
foo."bar"."setMe" = 'This is the string I set into Bar';
Without getProperty overriding you can achieve the same result using "${}" syntax for GString as the below code demonstrates
class Baz {
String something
}
class Bar {
Baz baz
}
class Foo {
Bar bar
}
def foo = new Foo()
foo.bar = new Bar()
foo.bar.baz = new Baz()
def target = foo
def path = ["bar", "baz"]
for (value in path) {
target = target."${value}"
}
target."something" = "someValue"
println foo.bar.baz.something
final println prints "someValue" as expected
Related
I created empty ArrayList of class objects and one class object. I added this class object with some parameters into ArrayList and then changed some parameters of this object. But class object that left in ArrayList also changed. That looks like I'm passing parameters by reference. Also, if I'm trying to create new object and make it equal with "=", that object becoming connected to old one, so if I'm changing first object then second one changing as well like reference to first variable. I've ran into same problem in Java (no surprise). So, how can I pass class object by value? I want to use one class object to add new objects into ArrayList and then change it without changing class object inside ArrayList.
class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
classObject.someData = 5
testArrayList.add(classObject)
classObject.someData = 7
testArrayList.add(classObject)
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData) //Output = 777. Needed 357
}
Same with creating new objects
class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
var secondClassObject : TestClass = classObject
testArrayList.add(secondClassObject)
classObject.someData = 5
var thirdClassObject : TestClass = classObject
testArrayList.add(thirdClassObject)
classObject.someData = 7
var fourthClassObject : TestClass = classObject
testArrayList.add(classObject)
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData) //Output = 777. Needed 357
}
You try to make similar code in Java because arrayList in Java works the same in this situation. So, you can send answer in Java code
You are basically adding the same instance of TestClass over and again with modified value, so the instances in array position 3 will also point to same instance of 1, if you really want different values, you need to either create a different instances, or use data class with copy which copies the values into different instance and you can named parameters to change values you need as below
data class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
testArrayList.add(classObject.copy(someData = 5))
testArrayList.add(classObject.copy(someData = 7))
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData)
}
copy
To copy an object for changing some of its properties, but keeping the
rest unchanged, use the copy() function.
class TestClass(var someData : Int = 0) {
fun copy(someData: Int = this.someData) = TestClass(someData)
}
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
testArrayList.add(classObject.copy(someData = 5))
testArrayList.add(classObject.copy(someData = 7))
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData)
}
I have a class that looks like this:
class Data {
#JsonCreator
public Data(#JsonProperty("string") String s, Widget w) {
string = s;
widget = w;
}
String string;
Widget widget;
}
I want to deserialize it from this from JSON like
{
"string": "string value"
}
When deserializing, I want to set widget to a shared instance. I have that instance when I create the object mapper, but I can not see how to tell Jackson to use this instance.
I see JsonDeserialize.getNullValue and getEmptyValue, but those look like they are for handling
{
"string": "string value", "widget": null
}
which is not the JSON that I have.
You could try #JacksonInject:
public class Data {
#JacksonInject
public Widget widget;
...
}
And then use as follows:
Widget widget = ...
InjectableValues injectable = new InjectableValues.Std().addValue(Widget.class, widget);
Data data = new ObjectMapper().reader(injectable).forType(Data.class).readValue(json);
So the problem is as follows. I am unit testing a class SampleClass using Rhino Mocks 3.6. For the tests I use a mock of InnerClass as it is used in the SampleClass constructor. InnerClass has a method called TheMethod(ref string s1,ref string s2). Here is where the problem begins. TheMethod(ref string,ref string) is doing nothing with the parameters and I want TheMethod to actually modify one of the strings (s1). Is it possible, using Rhino Mocks, to do such thing? If so, then how? WhenCalled? Do() handler? I'm clueless. Here's the pseudocode
Class SampleClass
{
Public String SampleClassMethod()
{
string s1 = string.Empty;
string s2 = string.Empty;
string s_final = this.InnerClass.TheMethod(ref s1, ref s2); //TheMethod() which is doing
//nothing with the given strings
if (s_final == "something")
return s1;
}
}
The result is, that s1 is unchanged and for the testing reasons I would like the TestMethod() to modify s1's value WITHOUT changing the body of TheMethod() itself
[TestMethod]
public void TestMethod1()
{
//generating mocks
//SampleClass target; //tested class object
Expect.Call(InnerClassMock.TheMethod(
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy,
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy)).IgnoreArguments();
string temp = target.SampleClassMethod();
Assert.AreEqual("1234", temp);
}
Assuming your inner class looks something like this (Note that TheMethod is virtual):
public class SomeClass
{
public virtual string TheMethod(ref string s1, ref string s2)
{
s1 = "X";
s2 = "Y";
return "Z";
}
}
You can use Rhino.Mock's "OutRef" option to define output for ref arguments:
var mock = MockRepository.GenerateStub<SomeClass>();
string temp1 = "", temp2 = "";
mock.Stub(m => m.TheMethod(ref temp1, ref temp2)).OutRef("AAA", "BBB").Return("DEF");
var my1 = "";
var my2 = "";
var result = mock.TheMethod(ref my1, ref my2);
After running this code, my1 will be "AAA", my2 will be "BBB" and result will be "DEF".
Dart specification states:
Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the
analogs of instanceOf, casts, typecase etc. in other languages).
Sounds great, but there is no instanceof-like operator. So how do we perform runtime type-checking in Dart? Is it possible at all?
The instanceof-operator is called is in Dart. The spec isn't exactly friendly to a casual reader, so the best description right now seems to be http://www.dartlang.org/articles/optional-types/.
Here's an example:
class Foo { }
main() {
var foo = new Foo();
if (foo is Foo) {
print("it's a foo!");
}
}
Dart Object type has a runtimeType instance member (source is from dart-sdk v1.14, don't know if it was available earlier)
class Object {
//...
external Type get runtimeType;
}
Usage:
Object o = 'foo';
assert(o.runtimeType == String);
As others have mentioned, Dart's is operator is the equivalent of Javascript's instanceof operator. However, I haven't found a direct analogue of the typeof operator in Dart.
Thankfully the dart:mirrors reflection API has recently been added to the SDK, and is now available for download in the latest Editor+SDK package. Here's a short demo:
import 'dart:mirrors';
getTypeName(dynamic obj) {
return reflect(obj).type.reflectedType.toString();
}
void main() {
var val = "\"Dart is dynamically typed (with optional type annotations.)\"";
if (val is String) {
print("The value is a String, but I needed "
"to check with an explicit condition.");
}
var typeName = getTypeName(val);
print("\nThe mirrored type of the value is $typeName.");
}
There are two operators for type testing: E is T tests for E an instance of type T while E is! T tests for E not an instance of type T.
Note that E is Object is always true, and null is T is always false unless T===Object.
Exact type matching is done via runtimeType property. Checking if an instance or any of its parent types (in the inheritance chain) is of the given type is done via is operator:
class xxx {}
class yyy extends xxx {}
void main() {
var y = yyy();
print(y is xxx);
print(y.runtimeType == xxx);
}
Returns:
true
false
Simply use .runtimeType on the property like below,
print(unknownDataTypeProperty.runtimeType)
Just to clarify a bit the difference between is and runtimeType. As someone said already (and this was tested with Dart V2+) the following code:
class Foo {
#override
Type get runtimeType => String;
}
main() {
var foo = Foo();
if (foo is Foo) {
print("it's a foo!");
}
print("type is ${foo.runtimeType}");
}
will output:
it's a foo!
type is String
Which is wrong.
Now, I can't see the reason why one should do such a thing...
T is The type
print( T.runtimeType)
if(value is int ) Returns true if the type of the value is int,
else if(value is! int )
To check the type of a variable use runtimeType
void main() {
int a = 10;
print(a.runtimeType);
}
to check whether the type of a variable is the same as your expected use is or runtimeType
void main() {
int a = 10;
print(a.runtimeType == int); // true
//or
print(a is int); // true
}
print("enter your phone number:\n");
var phone number = stdin.readLineSync();
if(phone number.runtimeType is int == true) // checks if the values input are integers
{
print('you have successfully input your phone number!');
}
else{
print('only numbers are allowed');
}
As part of my project, I am trying to build a web UI where user will select a method and pass the values. My program should be able to call the method dynamically and build a parameter list on runtime to pass it to the method.
I have created a comma separated list (string) of key and value pairs. This key/value pair is nothing but the parameter name and value of my method (methodname stored in a variable). Example: string params = "ID:123;Name:Garry;Address:addressObject;AddressLine:108 Plaza Lane;City:Avenel;State:NJ;Zip:07001;". Where ID and Name are simple string varaibles while Address is user defined type. What follows after Address i.e. AddressLine, City, State and Zip is elements of Address object. And my method definition is
public string GetInfo(string ID, string Name, Address addressObject)
{
//return something;
}
I am dynamically calling the method (GetInfo) that is stored in sMethodName variable using DynamicProxy like :
string sMethodName = "GetInfo";
object result = (object) proxy.CallMethod(sMethodName, arguments);
Challenge is how to pass the argument list dynamically? Till now I am just able to extract the values from the csv variable into NamedValueCollection. Here is the code:
public static void StoreParameterValues(string param)
{
nvc = new NameValueCollection();
param = param.TrimEnd(';');
string[] parameters = param.Split(new char[] { ';' });
foreach (string val in parameters)
{
string[] keyValue = val.Split(new char[] { ':' });
nvc.Add(keyValue[0], keyValue[1]);
}
}
..and here is the code that tries to build the parameter:
string methodName = "GetInfo";
DynamicProxyFactory factory = new DynamicProxyFactory("http://../myservice.svc");
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name;
}
DynamicProxy proxy = factory.CreateProxy(sContract);
string[] values = null;
// Create the parameter list
object[] arguments = new object[nvc.Count];
int i = -1;
foreach (string key in nvc.Keys)
{
values = nvc.GetValues(key);
foreach (string value in values)
{
arguments[++i] = value;
}
}
object result = (object) proxy.CallMethod(methodName, arguments);
The above code works if I have simple primitive types but not sure how can I build the logic for any other userdefined types. How can I create a object dynamically of type stored in a variable? Not sure if I was able to put my question correctly. I hope so :)
Edit: 01/19/2011: Applied the suggestion from Chris - using Reflection instead of ComponentModel.
I have converted the code to make it more generic. This works now for all primitive and custom types (resursion). Code snippet below:
private object BuildParameterList(Type type)
{
object item = new object();
item = Activator.CreateInstance(type);
PropertyInfo[] propArray = type.GetProperties(BindingFlags.Public|BindingFlags.Instance);
for (int i = 0; i < propArray.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propArray[i];
////Check for custom type
if (IsCustomType(pi.PropertyType))
{
object item1 = BuildParameterList(pi.PropertyType);
pi.SetValue(item, item1, null);
}
else
{
if (property.ContainsKey(pi.Name))
{
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
}
}
}
return item;
}
But if one of the property is Color (I just tested with Color type, will fail with other system types aswell-i guess), then it fails at the following line. Not sure how to handle system types - Color or something similar.
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
Can you not find what types are expected by the method, by inspecting its ParameterInfos:
endpoint.Contract.ContractType.GetMethod(methodName).GetParameters();
and then instantiating the custom types using:
Activator.CreateInstance(parameterType);