Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kevin Jump 2342 posts 14889 karma points MVP 8x c-trib
    Dec 15, 2020 @ 12:05
    Kevin Jump
    0

    Advice - how can you make something compatibe with versions with diffrent interfaces ?

    I suspect i know the answer to this, but advice would be welcome.

    I want to keep uSync fully v8 backward compatible (that is one version works with v8.0 all the way through to v8.10)- but just noticed in v8.6 the interface for IRelationType changed (see https://github.com/umbraco/Umbraco-CMS/pull/7303)

    principally the GUID values when nullable :

        [DataMember]
     -  Guid ParentObjectType { get; set; }
     +  Guid? ParentObjectType { get; set; }
    

    So now code qurying Relation Types with code compiled pre v8.6 will fail on 8.6+ because the method has changed - equally code compiled against 8.6+ will fail on older versions. (not many people will be using usync for relations because we don't sync the core ones, and its only if you add your own and turn on relation syncing)

    So any options - to keep cross version compatibility in one solution ?

    As i see it.

    1. Compile two versions and have two versions of a package (support headace)
    2. Separate out the relationship code into two diffrent dlls' one compiled pre 8.6 one after, and then in the code load the relevant one based on the version of umbraco you are running (results in two new dlls added to the project)
    3. Some fancy reflection thing ? that you could probably do but i don't know enough about reflection to do it ?

    I am hoping someone has an idea about number 3 or a better number 4 ?

  • Jeroen Vantroyen 54 posts 394 karma points c-trib
    Dec 15, 2020 @ 12:58
    Jeroen Vantroyen
    0

    I feel that #1 would be a hassle and #2 just feels icky.

    I'm not one to shy away from reflection, so I would give #3 a go.

    I could whip something up.

  • Kevin Jump 2342 posts 14889 karma points MVP 8x c-trib
    Dec 15, 2020 @ 13:09
    Kevin Jump
    0

    Hi,

    I think i have the skeleton of No3 now.

    some helper methods to get/set the guids.

       private Guid? GetGuidValue(IRelationType item, string propertyName)
        {
            var propertyInfo = item.GetType().GetProperty(propertyName);
            if (propertyInfo == null) return null;
    
            var value = propertyInfo.GetValue(item);
            if (value == null) return null;
    
            if (value is Guid guid)
            {
                return guid;
            }
    
            return null;
        }
    
        private void SetGuidValue(object item, string propertyName, Guid? value)
        {
            var propertyInfo = item.GetType().GetProperty(propertyName);
            if (propertyInfo == null) return;
    
            if (propertyInfo.PropertyType == typeof(Guid?))
            {
                propertyInfo.SetValue(item, value);
            }
            else if (propertyInfo.PropertyType == typeof(Guid) && value != null)
            {
                propertyInfo.SetValue(item, Guid.Empty);
            }
        }
    

    and a reflection method to find the new constructor should it exist (still testing all of this)

     private RelationType CreateRelation(string name, string alias, bool isBidrectional, Guid? parent, Guid? child)
        {
            // public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType)
    
            var t = typeof(RelationType);
            var types = new Type[5];
            types[0] = typeof(string);
            types[1] = typeof(string);
            types[2] = typeof(bool);
            types[3] = typeof(Guid?);
            types[4] = typeof(Guid?);
    
            var constructorInfoObj = t.GetConstructor(types);
            if (constructorInfoObj != null)
            {
                var parameters = new object[5];
                parameters[0] = name;
                parameters[1] = alias;
                parameters[2] = isBidrectional;
                parameters[3] = parent;
                parameters[4] = child;
    
                var obj = constructorInfoObj.Invoke(parameters);
                return (RelationType)obj;
            }
            else
            {
                return new RelationType(child.Value, parent.Value, alias);
            }
    
        }
    

    but equally i am just pasting from docs here, so if there is a better/nicer/more robust way....

  • Jeroen Vantroyen 54 posts 394 karma points c-trib
    Dec 15, 2020 @ 13:32
    Jeroen Vantroyen
    1

    Hi,

    I see your almost there :-).

    Without actually trying this out, I would say the below code in GetGuidValue() adds nothing (but also doesn't break anything).

    if (value == null) return null;
    

    In SetGuidValue() however, I believe it doesn't actually assign any value when it's a Guid and not Guid? ...

    propertyInfo.SetValue(item, Guid.Empty);
    

    I think you mean to assign value.Value, no?

    propertyInfo.SetValue(item, value.Value);
    

    The constructor-approach looks solid.

  • Kevin Jump 2342 posts 14889 karma points MVP 8x c-trib
    Dec 15, 2020 @ 18:59
    Kevin Jump
    0

    thanks for the sanity check - it does need some tidy up and yeah i got the nulls and empties mixed up.

    I "think" i am going to go with if there is no value then don't do the set (i was thinking Guid.Empty on legacy sites, but that might actually cause other problems,.

Please Sign in or register to post replies

Write your reply to:

Draft