Example #1
0
        /// <summary>
        ///     Reads this Item's value from it's source and, if the read value is different from the present value of the
        ///     <see cref="Value"/> property, updates the Value and fires the <see cref="Changed"/> event by invoking the
        ///     <see cref="Write"/> method and passing the read value.
        /// </summary>
        /// <remarks>
        ///     If the <see cref="ItemSource"/> of the Item is <see cref="ItemSource.Item"/>, the value is retrieved from the
        ///     <see cref="ReadFromSource"/> method of the <see cref="SourceItem"/>. If the ItemSource is
        ///     <see cref="ItemSource.Provider"/>, the value is retrieved from the <see cref="Provider"/> object's
        ///     <see cref="IItemProvider.Read(Item)"/> method. If the ItemSource is <see cref="ItemSource.Unknown"/>, the present
        ///     value of the <see cref="Value"/> property is returned. If the ItemSource is <see cref="ItemSource.Unresolved"/>, a
        ///     null value is returned.
        /// </remarks>
        /// <returns>The retrieved value.</returns>
        /// <threadsafety instance="true"/>
        public virtual object ReadFromSource()
        {
            // recursively call ReadFromSource() on each child in this Item's children collection this allows us to update whole
            // branches of the model with a single read
            if (HasChildren)
            {
                IList <Item> children;

                childrenLock.EnterReadLock();

                try
                {
                    children = Children;
                }
                finally
                {
                    childrenLock.ExitReadLock();
                }

                foreach (Item child in Children)
                {
                    child.ReadFromSource();
                }
            }

            // prepare a variable to hold the read result
            object      value   = new object();
            ItemQuality quality = ItemQuality.Good;

            // if the source is an Item, return the result from that Item's ReadFromSource() method. This will recursively refresh
            // each Item in the chain until the last Item (that which the Source = ItemProvider) is refreshed directly from the source.
            if (Source == ItemSource.Item)
            {
                sourceItemLock.EnterReadLock();

                try
                {
                    value = SourceItem.ReadFromSource();
                }
                finally
                {
                    sourceItemLock.ExitReadLock();
                }
            }
            else if (Source == ItemSource.Provider)
            {
                // if the source of this Item is an ItemProvider and it implements IReadable, return the value of the Read() method
                // for the provider. this will be the final read in the chain.
                providerLock.EnterReadLock();

                try
                {
                    value = Provider.Read(this);
                }
                catch (Exception)
                {
                    value   = null;
                    quality = ItemQuality.Bad;
                }
                finally
                {
                    providerLock.ExitReadLock();
                }
            }
            else if (Source == ItemSource.Unknown)
            {
                // if the source of this Item is unknown, the authoritative source for the Item's value is itself, so return the
                // Value property.
                valueLock.EnterReadLock();

                try
                {
                    value = Value;
                }
                finally
                {
                    valueLock.ExitReadLock();
                }
            }
            else if (Source == ItemSource.Unresolved)
            {
                // if the source of this Item is an unresolved FQN, return null.
                value   = null;
                quality = ItemQuality.Bad;
            }

            ChangeValue(value, quality);

            return(Read());
        }