vitorsousa pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6be38caeaec8e7808af9d0ab4b34465c84bb6e76

commit 6be38caeaec8e7808af9d0ab4b34465c84bb6e76
Author: Lauro Moura <lauromo...@expertisesolutions.com.br>
Date:   Thu Jul 11 15:52:52 2019 -0300

    csharp: Add helpers to get/set Values from Objects
    
    Summary:
    The user can construct an `Eina.Value` from a plain C# `object`, using
    reflection to get the correct type of object and construct the correct
    underlying C value.
    
    Also added the `Unwrap()` method to return a C# object representing the
    wrapped value.
    
    Both operations are useful when using `Eina.Value` to
    Get/Set values from `PropertyInfo` targets as in
    
    ```
    var v = new Eina.Value(propInfo.GetValue(sourceObj));
    ...
    propInfo.SetValue(targetObj, v.Unwrap());
    ```
    
    Currently, containers are not supported. It will be added in a following
    commit.
    
    Depends on D9270
    
    Reviewers: felipealmeida, vitor.sousa, segfaultxavi
    
    Reviewed By: vitor.sousa
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D9272
---
 src/bindings/mono/eina_mono/eina_value.cs | 170 +++++++++++++++++++++++++++++-
 src/tests/efl_mono/Value.cs               |  71 +++++++++++++
 2 files changed, 240 insertions(+), 1 deletion(-)

diff --git a/src/bindings/mono/eina_mono/eina_value.cs 
b/src/bindings/mono/eina_mono/eina_value.cs
index 898a4966bb..37412b679b 100644
--- a/src/bindings/mono/eina_mono/eina_value.cs
+++ b/src/bindings/mono/eina_mono/eina_value.cs
@@ -916,7 +916,86 @@ public class Value : IDisposable, IComparable<Value>, 
IEquatable<Value>
     private Value()
     {
         this.Handle = Alloc();
+
+        if (this.Handle == IntPtr.Zero)
+        {
+            throw new OutOfMemoryException("Failed to allocate memory for 
Eina.Value");
+        }
+
         this.Ownership = Ownership.Managed;
+        MemoryNative.Memset(this.Handle, 0, eina_value_sizeof());
+    }
+
+    /// <summary>Creates a new Value from the given C# value.</summary>
+    /// <param name="obj">The object to be wrapped.</param>
+    public Value(object obj) : this()
+    {
+        var objType = obj.GetType();
+
+        if (objType == typeof(sbyte))
+        {
+            Setup(ValueType.SByte);
+            Set((sbyte)obj);
+        }
+        else if (objType == typeof(byte))
+        {
+            Setup(ValueType.Byte);
+            Set((byte)obj);
+        }
+        else if (objType == typeof(short))
+        {
+            Setup(ValueType.Short);
+            Set((short)obj);
+        }
+        else if (objType == typeof(ushort))
+        {
+            Setup(ValueType.UShort);
+            Set((ushort)obj);
+        }
+        else if (objType == typeof(int))
+        {
+            Setup(ValueType.Int32);
+            Set((int)obj);
+        }
+        else if (objType == typeof(uint))
+        {
+            Setup(ValueType.UInt32);
+            Set((uint)obj);
+        }
+        else if (objType == typeof(long))
+        {
+            Setup(ValueType.Int64);
+            Set((long)obj);
+        }
+        else if (objType == typeof(ulong))
+        {
+            Setup(ValueType.UInt64);
+            Set((ulong)obj);
+        }
+        else if (objType == typeof(float))
+        {
+            Setup(ValueType.Float);
+            Set((float)obj);
+        }
+        else if (objType == typeof(double))
+        {
+            Setup(ValueType.Double);
+            Set((double)obj);
+        }
+        else if (objType == typeof(string))
+        {
+            Setup(ValueType.String);
+            Set(obj as string);
+        }
+        else if (typeof(Efl.Object).IsAssignableFrom(objType))
+        {
+            Setup(ValueType.Object);
+            Set(obj as Efl.Object);
+        }
+        else
+        {
+            throw new ArgumentException($"Unsupported type for direct 
construction: {objType}");
+        }
     }
 
     public Value(IntPtr handle, Ownership ownership = Ownership.Managed)
@@ -1390,6 +1469,95 @@ public class Value : IDisposable, IComparable<Value>, 
IEquatable<Value>
         return b;
     }
 
+    /// <summary>Unwrap the value into its underlying C# value.
+    ///
+    /// <para>Useful for methods like <see crev="PropertyInfo.SetValue(object, 
object)" />
+    /// as it will unpack the value to it correct C# type.</para>
+    /// </summary>
+    /// <returns>The C# value wrapped by this value.</returns>
+    public object Unwrap()
+    {
+        switch (GetValueType())
+        {
+            case ValueType.SByte:
+                {
+                    sbyte o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Byte:
+                {
+                    byte o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Short:
+                {
+                    short o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.UShort:
+                {
+                    ushort o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Int32:
+                {
+                    int o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.UInt32:
+                {
+                    uint o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Int64:
+            case ValueType.Long:
+                {
+                    long o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.UInt64:
+            case ValueType.ULong:
+                {
+                    ulong o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Float:
+                {
+                    float o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Double:
+                {
+                    double o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.String:
+                {
+                    string o;
+                    Get(out o);
+                    return o;
+                }
+            case ValueType.Object:
+                {
+                    Efl.Object o;
+                    Get(out o);
+                    return o;
+                }
+            default:
+                throw new InvalidOperationException($"Unsupported value type 
to unwrap: {GetValueType()}");
+        }
+    }
+
     // Efl.Object conversions are made explicit to avoid ambiguity between
     // Set(Efl.Object) and Set(Value) when dealing with classes derived from
     // Efl.Object.
@@ -1828,7 +1996,7 @@ public class Value : IDisposable, IComparable<Value>, 
IEquatable<Value>
         if (!GetValueType().IsString())
         {
             throw (new ArgumentException(
-                        "Trying to set non-string value on a string 
Eina.Value"));
+                        "Trying to set string value on a non-string 
Eina.Value"));
         }
 
         // No need to worry about ownership as eina_value_set will copy the 
passed string.
diff --git a/src/tests/efl_mono/Value.cs b/src/tests/efl_mono/Value.cs
index 75b8e96ca1..1c83344675 100644
--- a/src/tests/efl_mono/Value.cs
+++ b/src/tests/efl_mono/Value.cs
@@ -1029,5 +1029,76 @@ public static class TestEinaValue {
     /*     Test.Assert(false, "Implement me."); */
     /* } */
 }
+
+public static class TestValueFromObject
+{
+
+    private class Holder
+    {
+        public int Number { get; set; }
+        public double Factor { get; set; }
+        public string Name { get; set; }
+        public Efl.Object Obj { get; set; }
+    }
+
+    public static void TestConversionFromToObject()
+    {
+        var source = new Holder {
+            Number = 1984,
+            Factor = 3.14,
+            Name = "Orwell",
+            Obj = new Dummy.TestObject(),
+        };
+
+        {
+            var prop = source.GetType().GetProperty("Name");
+            var v = new Eina.Value(prop.GetValue(source));
+
+            Test.AssertEquals(v.GetValueType(), Eina.ValueType.String);
+            Test.AssertEquals((string)v, prop.GetValue(source));
+
+            Test.Assert(v.Set("New value"));
+            prop.SetValue(source, v.Unwrap());
+            Test.AssertEquals(prop.GetValue(source), "New value");
+        }
+
+        {
+            var prop = source.GetType().GetProperty("Factor");
+            var v = new Eina.Value(prop.GetValue(source));
+
+            Test.AssertEquals(v.GetValueType(), Eina.ValueType.Double);
+            Test.AssertAlmostEquals((double)v, (double)prop.GetValue(source));
+
+            Test.Assert(v.Set(2.78));
+            prop.SetValue(source, v.Unwrap());
+            Test.AssertEquals(prop.GetValue(source), 2.78);
+        }
+
+        {
+            var prop = source.GetType().GetProperty("Number");
+            var v = new Eina.Value(prop.GetValue(source));
+
+            Test.AssertEquals(v.GetValueType(), Eina.ValueType.Int32);
+            Test.AssertEquals((int)v, prop.GetValue(source));
+
+            Test.Assert(v.Set(2012));
+            prop.SetValue(source, v.Unwrap());
+            Test.AssertEquals(prop.GetValue(source), 2012);
+        }
+
+        {
+            var prop = source.GetType().GetProperty("Obj");
+            var v = new Eina.Value(prop.GetValue(source));
+
+            Test.AssertEquals(v.GetValueType(), Eina.ValueType.Object);
+            Test.AssertEquals((Efl.Object)v, prop.GetValue(source));
+
+            var newObj = new Dummy.TestObject();
+            Test.Assert(v.Set(newObj));
+            prop.SetValue(source, v.Unwrap());
+            Test.AssertEquals(prop.GetValue(source), newObj);
+        }
+    }
+}
 #pragma warning restore 1591
 }

-- 


Reply via email to