Example #1
0
 private static void ValidateDefaultValueCommon(object defaultValue, Type propertyType, string propertyName, ValidateValueCallback validateValueCallback, bool checkThreadAffinity)
 {
     if (!IsValidType(defaultValue, propertyType))
     {
         throw new ArgumentException(SR.Get("DefaultValuePropertyTypeMismatch", propertyName));
     }
     if (defaultValue is Expression)
     {
         throw new ArgumentException(SR.Get("DefaultValueMayNotBeExpression"));
     }
     if (checkThreadAffinity)
     {
         DispatcherObject dispatcherObject = defaultValue as DispatcherObject;
         if (dispatcherObject != null && dispatcherObject.Dispatcher != null)
         {
             ISealable sealable = dispatcherObject as ISealable;
             if (sealable == null || !sealable.CanSeal)
             {
                 throw new ArgumentException(SR.Get("DefaultValueMustBeFreeThreaded", propertyName));
             }
             Invariant.Assert(!sealable.IsSealed, "A Sealed ISealable must not have dispatcher affinity");
             sealable.Seal();
             Invariant.Assert(dispatcherObject.Dispatcher == null, "ISealable.Seal() failed after ISealable.CanSeal returned true");
         }
     }
     if (validateValueCallback != null && !validateValueCallback(defaultValue))
     {
         throw new ArgumentException(SR.Get("DefaultValueInvalid", propertyName));
     }
 }
Example #2
0
 public static void ThrowWhenSeal(this ISealable sealable, string errorMessage)
 {
     if (sealable.IsSealed)
     {
         throw new InvalidOperationException(errorMessage);
     }
 }
Example #3
0
            /// <summary>
            /// Recursively seal an object
            /// </summary>
            /// <param name="o">object to be recursively sealed</param>
            public void SealRecursively(object o)
            {
                // stop when we detect re-entry (reference loop)
                if (o == null || processStack.Contains(o))
                {
                    return;
                }

                // stops if o is not ISealable and we are not in deeper mode
                if (!(deeper || o is ISealable))
                {
                    return;
                }

                //if (isDebug) s_log.Debug("DeepSeal object: [" + o + "]");

                // keep track of objects being processed, so we can detect re-entry
                processStack.Push(o);

                try
                {
                    // we need to do generic collection first for two reasons:
                    // 1. this is by contract in none deeper mode. see the
                    //    documentation of DealSeal methods for detail.
                    // 2. if a dictionary implements both generic and non-generic,
                    //    foreach returns KeyValuePair instead of DictionaryEntry.
                    bool isProcessed = TryProcessGenericCollection(o);

                    // try to process as none generic collection
                    if (!isProcessed)
                    {
                        isProcessed = TryProcessCollection(o);
                    }

                    // if o is not a collection, seal its all properties.
                    if (!isProcessed)
                    {
                        DeepSealProperties(o);
                    }

                    // seal the object itself
                    ISealable s = o as ISealable;
                    if (s != null && !s.IsSealed)
                    {
                        s.Seal();
                    }
                }
                finally
                {
                    processStack.Pop();
                }
            }
Example #4
0
 /// <summary>
 /// Recursively deep seal an instance of <see cref="ISealable"/> object.
 /// </summary>
 /// <remarks>
 /// <para>
 /// <c>DeepSeal</c> walks through the collection items or object properties
 /// to find all <c>ISealable</c> objects. It recursively deep seals
 /// each <c>ISealable</c> it found. Then it seals the object itself.
 /// </para>
 /// <para>
 /// This methods only seals and recusively seals the <c>ISealable</c> object
 /// and its <c>ISealable</c> members. In other words, the recursively walks
 /// through elements of arrays, collections and properties, but the recursivity
 /// stops at any element that is not <c>ISealable</c>.
 /// <see cref="DeeperSeal"/> take one step
 /// further that it works on any object and seach for all its decending
 /// objects for <c>ISealable</c> objects and then seal them.
 /// </para>
 /// <para>
 /// Below is the pseudo code of deep sealing logic. Please note that the
 /// implementation can be very different as long as the same result is
 /// achieved.
 /// </para>
 /// <code>
 /// public static void DeepSeal(ISealalbe o) {
 ///   if (o is re-entered) return; // handles the looped reference
 ///   if (o is generic IDictionary(of TKey, TValue)) {
 ///     foreach (pair in o) {
 ///       if (TKey is assignable to ISealable)
 ///         DeepSeal(pair.key);
 ///       if (TValue is assignalbe to ISealable)
 ///         DeepSeal(pair.value);
 ///     }
 ///   } else if (o is generic ICollection(of T) and T assingable to ISealable) {
 ///     // this handles array as well, because array is a collection
 ///     foreach (item in o) DeepSeal(item);
 ///   } else if (o is non-generic IDictionary) {
 ///     foreach (entry in o) {
 ///       if (entry.key is ISealable) DeepSeal(entry.key);
 ///       if (entry.value is ISealable) DeepSeal(entry.value);
 ///     }
 ///   } else if (o is non-generic collection) {
 ///     foreach (item in o) {
 ///       if (item is ISealable) DeepSeal(item);
 ///     }
 ///   } else {
 ///     foreach (public property of o) {
 ///       if (type of property is assignable to ISealable) DeepSeal(property);
 ///     }
 ///   }
 ///   if (!o.isSealed) o.Seal()
 /// }
 /// </code>
 /// </remarks>
 /// <param name="o">the sealable to be deep sealed</param>
 /// <seealso cref="DeeperSeal"/>
 public static void DeepSeal(ISealable o)
 {
     new DeepSealer(false).SealRecursively(o);
 }
Example #5
0
        private static void ValidateDefaultValueCommon(
            object defaultValue,
            Type propertyType,
            string propertyName,
            ValidateValueCallback validateValueCallback,
            bool checkThreadAffinity)
        {
            // Ensure default value is the correct type
            if (!IsValidType(defaultValue, propertyType))
            {
                throw new ArgumentException(SR.Format(SR.DefaultValuePropertyTypeMismatch, propertyName));
            }

            // An Expression used as default value won't behave as expected since
            //  it doesn't get evaluated.  We explicitly fail it here.
            if (defaultValue is Expression)
            {
                throw new ArgumentException(SR.DefaultValueMayNotBeExpression);
            }

            if (checkThreadAffinity)
            {
                // If the default value is a DispatcherObject with thread affinity
                // we cannot accept it as a default value. If it implements ISealable
                // we attempt to seal it; if not we throw  an exception. Types not
                // deriving from DispatcherObject are allowed - it is up to the user to
                // make any custom types free-threaded.

                DispatcherObject dispatcherObject = defaultValue as DispatcherObject;

                if (dispatcherObject != null && dispatcherObject.Dispatcher != null)
                {
                    // Try to make the DispatcherObject free-threaded if it's an
                    // ISealable.

                    ISealable valueAsISealable = dispatcherObject as ISealable;

                    if (valueAsISealable != null && valueAsISealable.CanSeal)
                    {
                        Invariant.Assert(!valueAsISealable.IsSealed,
                                         "A Sealed ISealable must not have dispatcher affinity");

                        valueAsISealable.Seal();

                        Invariant.Assert(dispatcherObject.Dispatcher == null,
                                         "ISealable.Seal() failed after ISealable.CanSeal returned true");
                    }
                    else
                    {
                        throw new ArgumentException(SR.Format(SR.DefaultValueMustBeFreeThreaded, propertyName));
                    }
                }
            }


            // After checking for correct type, check default value against
            //  validator (when one is given)
            if (validateValueCallback != null &&
                !validateValueCallback(defaultValue))
            {
                throw new ArgumentException(SR.Format(SR.DefaultValueInvalid, propertyName));
            }
        }
Example #6
0
 public static void ThrowWhenSeal(this ISealable sealable)
 {
     sealable.ThrowWhenSeal(DefaultErrorMessage);
 }