Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DictionaryAdapter Nesting Dictionaries JSON like #673

Open
winxalex opened this issue Nov 23, 2023 · 0 comments
Open

DictionaryAdapter Nesting Dictionaries JSON like #673

winxalex opened this issue Nov 23, 2023 · 0 comments

Comments

@winxalex
Copy link

winxalex commented Nov 23, 2023

Case: Response from api in JSON like Dictionaries (<string,object>,<object,object> )and List
Expando Object as candidate but not working in .NET Core 2.1 (would to be good benchmarking Expando Vs DictionaryAdapter)

using System;
using System.Collections;
using Castle.Components.DictionaryAdapter;

namespace x
{
    public class DictionaryAdapterAttribute : DictionaryBehaviorAttribute,
        IPropertyDescriptorInitializer, IDictionaryPropertyGetter
    {
        private Type __type;

      
        public DictionaryAdapterAttribute(Type type)
        {
            __type = type;
        }


        public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue,
            PropertyDescriptor property, bool ifExists)
        {
            if (storedValue != null && storedValue.GetType().IsGenericType &&
                storedValue is IDictionary dictionary)
            {
                var adapter = dictionaryAdapter.Meta.Factory.GetAdapter(__type,
                    dictionary);

                dictionaryAdapter.SetProperty(key, ref adapter);
               
            }

            return storedValue;
        }

        public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
        {
            propertyDescriptor.Fetch = true;
        }
    }
}



using System;
using System.Collections;
using System.Collections.Generic;
using Castle.Components.DictionaryAdapter;

namespace X
{
     /// <summary>
        ///  will convert List<Dictionaries> to List<of addapters of Dictionaries>(default) or some other Collection Class
        ///  which should have constructor accepting IEnumerable
        /// </summary>
        public class ListOfDictionariesAdapterAttribute : DictionaryBehaviorAttribute,
            IPropertyDescriptorInitializer, IDictionaryPropertyGetter
        {
            private Type __type;
            private bool __adapted;

            public ListOfDictionariesAdapterAttribute(Type type)
            {
                __type = type;
            }


           

            public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue,
                PropertyDescriptor property, bool ifExists)
            {
                // var o = dictionaryAdapter.GetProperty(key, ifExists);

                if (!__adapted && storedValue != null && storedValue.GetType().IsGenericType &&
                    storedValue is IEnumerable enumerable)
                {
                    
                    if (enumerable.GetType().GetGenericArguments()[0] != __type)
                    {
                        var enumerator = enumerable.GetEnumerator();
                        var genericArgument = __type.GetGenericArguments()[0];
                        IList ilistWrapper =
                            Activator.CreateInstance(typeof(List<>).MakeGenericType(genericArgument)) as IList;
                       
                        while (enumerator.MoveNext())
                        {
                            if (enumerator.Current is IDictionary current)
                                ilistWrapper?.Add(dictionaryAdapter.Meta.Factory.GetAdapter(genericArgument,
                                    current));
                        }

                        object list;
                        
                        if (__type.GetGenericTypeDefinition()==typeof(List<>))
                        {
                            //instead of List<Dictionaries> swap with List<adapters of Dictionaries>
                            list = ilistWrapper;
                        }
                        else
                        {
                            //!! Note maybe use https://github.com/GriffinPlus/dotnet-libs-fastactivator instead of 
                            //collection must have constructor that accept enumerable as params
                            list = Activator.CreateInstance(__type, ilistWrapper);

                            //v2 only for ObservableLinkedList,List
                            // var methodInfo = list.GetType().GetMethod("AddLast",new Type[]{genericArgument});
                            //
                            // enumerator.Reset();
                            //
                            // while (enumerator.MoveNext())
                            // {
                            //     var adapter = dictionaryAdapter.Meta.Factory.GetAdapter(genericArgument,
                            //         (IDictionary) enumerator.Current);
                            //     methodInfo?.Invoke(list,new object[]{adapter});
                            // }
                        }

                        dictionaryAdapter.SetProperty(key, ref list);

                        __adapted = true;
                    }
                }


                return storedValue;
            }

            public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
            {
                propertyDescriptor.Fetch = true;
            }
        }
}

Now with attributes DicitonaryAdapter will support nesting even lists.

  public interface ICharacter:IElement
    {
        

        [adapter.DictionaryAdapter(typeof(ICharacterProperties))]
        ICharacterProperties properties { get; set; }
   

      [ListOfDictionariesAdapterAttribute(typeof(List<IGoal>))]
        List<IGoal> goals { get; set; }
    }



    public interface IElement
    {
        string label { get; set; }
        long id { get; set; }
    }


...other interfaces

Hope this the way. Hope someone find helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant