Announcement

Collapse
No announcement yet.

Identify literal objects at runtime

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Marco
    started a topic Identify literal objects at runtime

    Identify literal objects at runtime

    Hi

    At runtime I'm trying to find out whether an object instance's type is a "real" Bridge object or just an object literal. I tried the following approach:
            var type = cust.GetType() ;
            if (type != null)
            {
                var attr = type.GetCustomAttributes(typeof(ObjectLiteralAttribute), false);
    
                if (attr.Any())
                {
                    Console.WriteLine("is literal object");
                }
            }
            else
            {
                  Console.WriteLine("is literal object");
            }
    However, this throws an exception:
    Bridge.Contract.EmitterException: Type Bridge.ObjectLiteralAttribute is marked as not usable from script
    What is your recommended way to distinguish between real objects and literals ?

    Thanks,
    Marco

  • Andrey
    replied
    Marco, thanks for sharing that deck, looks very nice!

    geoffrey.mcgill, good idea with Retyped.es5, below is the sample where all dynamic andScript.Write statements are replaced with the corresponding type safe API:
    https://deck.net/4d5d4a6ab95907e63f7644b3450b9b2f

    Leave a comment:


  • geoffrey.mcgill
    replied
    Hi Marco. Looks cool.

    If you're using Retyped, you can remove those Script.Write calls:

    https://deck.net/ce8a49ddad9c214b48bee4b791ed6e83

    Leave a comment:


  • Marco
    replied
    For anyone interested, now I even got inheritance working and made everything dynamic:

    https://deck.net/313a7f1daf71620d8ddcf9ba7c3fac6e
    Last edited by Marco; 2018-05-21 @ 10:03 PM.

    Leave a comment:


  • Marco
    replied
    Thanks so much for this insight, it helped me a lot! I was able to inject my own setter in a PoC.. check it out here:

    https://deck.net/38148b02abb4c04602ac60e5e15da11a
    (the sample is still using static property name, but it should be easy to make everything dynamic)

    I was able to wrap the original Bridge setter with my own setter, which can then trigger a change notification. Pretty cool, isn't it? I just hope I'm not messing too deep inside Bridget.net... wouldn't want to break my apps down the road.

    Thanks again.

    Leave a comment:


  • Andrey
    replied
    The reason why property definitions disappeared from output is that Bridge initially declares them on prototype scope, and then they're inherited by an instance. But GetOwnPropertyNames() method retrieves own properties only, not inherited. If we used prototype, we'd be able to get those properties along with some internals:

    https://deck.net/3cd93284c4bbf4e0de8904f28288a9a5

    foreach (var key in object.GetOwnPropertyNames(cust.GetType().Prototype))
    {
       Console.WriteLine("Detected property:" + key);        
    }
    But I guess using prototype object also implies on the knowledge whether an object is an instance of Bridge class or not. More generic approach could be achieved by applying AutoPropertyRule.Plain rule, of course if it fits your requirements. Setting that rule will instruct Bridge to generate properties as simple object fields and basically avoid usage of Object.defineProperty().

    https://deck.net/514e27dbe287ac1e98c2def2de6a0538

    [Rules(AutoProperty = AutoPropertyRule.Plain)]
    //[ObjectLiteral]
    public class Customer: Contact
    {
       public string Name { get; set; }
    }

    Leave a comment:


  • Marco
    replied
    Hi Andrey

    Thanks a lot. Maybe we can go about this question in another way. The reason I need to distinguish between plan/bridge is because I'm trying to write my own databinder in Bridge.NET, similar to vue.js. In order to detect property value changes, I need to inject property setters, which is also the recommended way by vue.js (see: https://vuejs.org/v2/guide/reactivity.html).

    I have a PoC working for plain objects, but I keep failing with "real" bridge objects, and I can't figure out why. Here's an example:

    https://deck.net/f75f6421a6cd8df43a66208bf168f18d

    This works fine, but once you remove the [ObjectLiteral] attributes from the two classes Contact and Customer, there are no property definitions left in a JavaScript sense.

    I know about the AOP feature of Bridge.NET which would allow me to inject INotifyPropertyChanged into every object. But I'm trying to find a more generic solution to this problem so that the user (developer) of my framework doesn't have to think about databinding-requirements when designing classes. It should "just work" at runtime.

    Any ideas?
    Thanks,
    Marco

    Leave a comment:


  • Andrey
    replied
    Hi Marco,

    Indeed, Bridge attributes are non-scriptable, so there is no any information about them at runtime.

    I've been thinking about utilizing Bridge.isPlainObject function for object literal identification:
    [Template("Bridge.isPlainObject({0})")]
    public static extern bool IsPlainObject(object o);
    However, it will return false for external type instances, see the full sample here:
    https://deck.net/68786024893bfe60d5ad8924e46ffbd9

    I think a Bridge type could be identified by internal fields like $init, $name etc.
    We'll investigate whether there is a more solid way of doing that and will get back to you with the results.

    Leave a comment:


  • Marco
    replied
    PS: It would be nice if your solution could also detect external objects as literals... IOW, instances passed from external libraries should be considered literals as well.

    Leave a comment:

Working...
X