public static void Main()
 {
     DetectingAttributes.Go();
     MatchingAttributes.Go();
     ConditionalAttributeDemo.Go();
 }
        /// <summary>
        ///   Create a new dependency property factory for a specific set of properties.
        /// </summary>
        /// <param name = "ownerType">The owner type of the dependency properties.</param>
        /// <param name = "enforceNamingConventions">
        ///   Whether or not to throw exceptions when the naming conventions aren't followed.
        ///   See http://msdn.microsoft.com/en-us/library/bb613563.aspx.
        /// </param>
        /// <param name = "checkForStatic">Whether or not to check whether the factory is static.</param>
        protected DependencyPropertyFactory(Type ownerType, bool enforceNamingConventions, bool checkForStatic)
            : base(ownerType, true)
        {
            Contract.Requires(typeof(T).IsPublic || typeof(T).IsNestedPublic);

            Properties            = new Dictionary <T, DependencyProperty>();
            _enforceWpfConvention = enforceNamingConventions;

            // When coercion is used, all enum values should be independent flag values, different from 0.
            if (MatchingAttributes.Any(a => a.Key.GetAttributes <CoercionHandlerAttribute>().Length > 0))
            {
                T    none     = default(T);
                Type enumType = typeof(T);
                bool correctImplementation =
                    enumType.IsFlagsEnum() &&
                    EnumHelper <T> .GetValues().All(v => EnumHelper <T> .GetFlaggedValues(v).Count() == 1 && !v.Equals(none));

                if (!correctImplementation)
                {
                    string message = String.Format(
                        "In order to use coercion, each enum value of {0} should be an individual flag value, different from 0.", enumType);
                    throw new InvalidImplementationException(message);
                }
            }

            // Check whether the factory itself is defined as a static field.
            // TODO: Can part of this logic be moved to ReflectionHelper?
            if (checkForStatic)
            {
                FieldInfo[] fields = OwnerType.GetFields(
                    BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                bool validFactory
                    = fields
                      .Where(field => field.FieldType == typeof(DependencyPropertyFactory <T>) && field.IsStatic)
                      .Any();
                if (!validFactory)
                {
                    throw new InvalidImplementationException(
                              "Incorrect usage of DependencyPropertyFactory in class '" + OwnerType.Name + "'. " +
                              "A DependencyPropertyFactory needs to be created as a static field inside it's owner class.");
                }
            }

            // Check whether callback attributes are applied to non-static functions. They should be static!
            var callbackMethods =
                from method in OwnerType.GetMethods(ReflectionHelper.FlattenedClassMembers)
                from attribute in method.GetAttributes <AbstractDependencyPropertyCallbackAttribute>()
                select method;

            if (!callbackMethods.All(m => m.IsStatic))
            {
                throw new InvalidImplementationException(
                          "Not all dependency property callback functions are defined as static in type '" + OwnerType.Name + "'.");
            }

            // Create dependency properties.
            var properties =
                from item in MatchingAttributes
                where item.Key is PropertyInfo
                select item;

            foreach (var item in properties)
            {
                var attribute = (DependencyPropertyAttribute)item.Value[0];
                CreateDependencyProperty(GetDependencyPropertyInfo(item.Key as PropertyInfo, attribute));
            }

            // Create attached properties.
            var attachedProperties =
                from item in MatchingAttributes
                where item.Key is MethodInfo
                from attribute in item.Value
                group new
            {
                MemberInfo = item.Key,
                Attribute  = (DependencyPropertyAttribute)attribute
            } by attribute.GetId();

            foreach (var item in attachedProperties)
            {
                var  attachedProperty = item.ToList();
                bool valid            = false;
                if (attachedProperty.Count <= 2)
                {
                    MethodInfo[] methods = attachedProperty.Select(p => (MethodInfo)p.MemberInfo).ToArray();
                    MethodInfo   getter  = methods.Single(m => m.Name.StartsWith(GetPrefix));
                    MethodInfo   setter  = methods.SingleOrDefault(m => m.Name.StartsWith(SetPrefix) && m.ReturnType == typeof(void));

                    // Verify whether getter and setter correspond.
                    // TODO: Do typechecking of parameters?
                    if (setter != null && getter.Name.Substring(GetPrefix.Length) == setter.Name.Substring(SetPrefix.Length))
                    {
                        // Extract settings.
                        var attributes = attachedProperty.Select(a => a.Attribute).ToArray();
                        var id         = (T)attachedProperty.First().Attribute.GetId();
                        // TODO: Allow checking whether or not the default value is set or not.
                        var defaultValues =
                            attributes.Where(a => a.DefaultValue != null).Select(a => a.DefaultValue).ToArray();
                        var readOnlySettings =
                            attributes.Where(a => a.IsReadOnlySet()).Select(a => a.IsReadOnlySet() ? a.IsReadOnly() : new bool?()).ToArray();
                        if (!defaultValues.AllEqual() || !readOnlySettings.AllEqual())
                        {
                            throw new InvalidImplementationException(
                                      "All set options of \"" + typeof(DependencyPropertyAttribute) +
                                      "\" should correspond with attributes with the same ID." +
                                      " Preferably only set options on one of the attributes.");
                        }

                        DependencyPropertyInfo info = GetAttachedDependencyPropertyInfo(
                            getter, setter,
                            id, defaultValues.FirstOrDefault(), readOnlySettings.FirstOrDefault());

                        // HACK: For collections, use a dependency property with non-matching name so the getter is called the first time,
                        //       so it can be initialized and doesn't need to be initialized through XAML.
                        if (info.Type.ImplementsInterface(typeof(ICollection)))
                        {
                            info.Name = info.Name + "Internal";
                            _attachedCollectionsTypes.Add(info.Id, info.Type);
                        }

                        CreateDependencyProperty(info);
                        valid = true;
                    }
                }

                if (!valid)
                {
                    throw new InvalidImplementationException(
                              "Invalid usage of the attribute " + typeof(DependencyPropertyAttribute) + ". " +
                              "To create an attached property, apply it to a correctly named get and optionally corresponding set method. ");
                }
            }
        }