/// <summary>
        /// Invoked by an <see cref="Spring.Objects.Factory.IObjectFactory"/>
        /// after it has set all object properties supplied
        /// (and satisfied <see cref="Spring.Objects.Factory.IObjectFactoryAware"/>
        /// and ApplicationContextAware).
        /// </summary>
        /// <exception cref="System.Exception">
        /// In the event of misconfiguration (such as failure to set an essential
        /// property) or if initialization fails.
        /// </exception>
        public override void AfterPropertiesSet()
        {
            if (TargetType == null &&
                TargetObject == null)
            {
                throw new ArgumentException("One of the TargetType or TargetObject properties must be set.");
            }
            if (TargetProperty == null)
            {
                throw new ArgumentException("The TargetProperty property is required.");
            }
            Type         targetType    = null;
            BindingFlags propertyFlags = BindingFlags.Public | BindingFlags.IgnoreCase;

            if (TargetObject == null)
            {
                // a static property...
                propertyFlags |= BindingFlags.Static;
                targetType     = TargetType;
                if (TargetProperty.IndexOf(".") == -1)
                {
                    Property = targetType.GetProperty(TargetProperty, propertyFlags);
                }
                else
                {
                    // $?#@! a nested static property... recurse to the end property
                    string property      = TargetProperty;
                    int    propertyIndex = property.IndexOf(".");
                    string startProperty = property.Substring(0, propertyIndex);
                    Property       = targetType.GetProperty(startProperty, propertyFlags);
                    TargetObject   = Property.GetValue(null, new object[] {});
                    TargetProperty = property.Substring(propertyIndex + 1);
                    AfterPropertiesSet();
                }
            }
            else
            {
                // an instance property...
                propertyFlags |= BindingFlags.Instance;
                targetType     = TargetObject.GetType();

                // using the object wrapper does nested property lookup
                Property = _targetObjectWrapper.GetPropertyInfo(TargetProperty);
            }
            if (Property == null)
            {
                throw new InvalidPropertyException(targetType, TargetProperty);
            }
            if (!Property.CanRead)
            {
                throw new NotWritablePropertyException(TargetProperty, targetType);
            }
            base.AfterPropertiesSet();
        }