/// <summary>
        /// NOTE: Code-generation-invoked method, method name and parameter order matters
        /// </summary>
        /// <param name="cache">cache</param>
        /// <param name="getter">getter</param>
        /// <param name="object">object</param>
        /// <param name="eventAdapterService">event server</param>
        /// <returns>property</returns>
        public static Object CacheAndCall(CopyOnWriteList <DynamicPropertyDescriptor> cache, DynamicPropertyGetterBase getter, Object @object, EventAdapterService eventAdapterService)
        {
            var desc = GetPopulateCache(cache, getter, @object, eventAdapterService);

            if (desc.Method == null)
            {
                return(null);
            }
            return(getter.Call(desc, @object));
        }
        /// <summary>
        /// NOTE: Code-generation-invoked method, method name and parameter order matters
        /// </summary>
        /// <param name="cache">cache</param>
        /// <param name="getter">getter</param>
        /// <param name="object">object</param>
        /// <param name="eventAdapterService">event server</param>
        /// <returns>exists-flag</returns>
        public static bool CacheAndExists(CopyOnWriteList <DynamicPropertyDescriptor> cache, DynamicPropertyGetterBase getter, Object @object, EventAdapterService eventAdapterService)
        {
            var desc = GetPopulateCache(cache, getter, @object, eventAdapterService);

            if (desc.Method == null)
            {
                return(false);
            }
            return(true);
        }
        private static DynamicPropertyDescriptor GetPopulateCache(CopyOnWriteList <DynamicPropertyDescriptor> cache, DynamicPropertyGetterBase dynamicPropertyGetterBase, Object obj, EventAdapterService eventAdapterService)
        {
            // Check if the method is already there
            var target = obj.GetType();

            foreach (DynamicPropertyDescriptor desc in cache)
            {
                if (desc.Clazz == target)
                {
                    return(desc);
                }
            }

            // need to add it
            lock (dynamicPropertyGetterBase)
            {
                foreach (DynamicPropertyDescriptor desc in cache)
                {
                    if (desc.Clazz == target)
                    {
                        return(desc);
                    }
                }

                // Lookup method to use
                var method = dynamicPropertyGetterBase.DetermineMethod(target);

                // Cache descriptor and create fast method
                DynamicPropertyDescriptor propertyDescriptor;
                if (method == null)
                {
                    propertyDescriptor = new DynamicPropertyDescriptor(target, null, false);
                }
                else
                {
                    var fastClass  = FastClass.Create(target);
                    var fastMethod = fastClass.GetMethod(method);
                    propertyDescriptor = new DynamicPropertyDescriptor(target, fastMethod, fastMethod.ParameterCount > 0);
                }
                cache.Add(propertyDescriptor);
                return(propertyDescriptor);
            }
        }