/// <summary>
        /// Tries to set the specified member to the specified <paramref name="value"/>.
        /// </summary>
        /// <param name="binder">The binder.</param>
        /// <param name="value">The value to be set.</param>
        /// <returns><see langword="true"/> if the member is set; otherwise, <see langword="false"/>.</returns>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            Contract.Assume(binder != null);

            var comparison = binder.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            Contract.Assume(binder.Name != null);

            var property = ComponentReflection.GetProperty(source, binder.Name, comparison);

            if (property == null)
            {
                return(false);
            }

            if (property.IsReadOnly)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Errors.PropertyIsReadOnly, property.Name));
            }

            Action <object, object> action = property.SetValue;

            var invokeAsync = action.ToAsync();

            invokeAsync(source, value);

            return(true);
        }
        private bool TryGetPropertyObservable(string propertyName, StringComparison comparison, out object result)
        {
            Contract.Requires(propertyName != null);
            Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out result) != null);

            var property = ComponentReflection.GetProperty(source, propertyName, comparison);

            if (property == null)
            {
                result = null;
                return(false);
            }

            var changed = property.PropertyChanged(source).Select(_ => property.GetValue(source));

#if !SILVERLIGHT
            Contract.Assume(property.PropertyType != null);
#endif

            result = changed.Coerce(property.PropertyType);

            return(true);
        }
        /// <summary>
        /// Gets the names of the dynamic members.
        /// </summary>
        /// <returns>Sequence of dynamic member names.</returns>
        public override IEnumerable <string> GetDynamicMemberNames()
        {
            Contract.Ensures(Contract.Result <IEnumerable <string> >() != null);

            return(ComponentReflection.GetMembers(source).Select(member => member.Name));
        }
        private bool TryGetEventObservable(string eventName, StringComparison comparison, out object result)
        {
            Contract.Requires(eventName != null);
            Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out result) != null);

            var @event = ComponentReflection.GetEvent(source, eventName, comparison);

            if (@event == null)
            {
                result = null;
                return(false);
            }

#if !SILVERLIGHT
            Contract.Assume(@event.EventType != null);
#endif

#if WINDOWS_PHONE || PORT_45
            var isGeneric = @event.EventType.GetTypeInfo().IsGenericType;
#else
            var isGeneric = @event.EventType.IsGenericType;
#endif

            Type eventArgsType;

            if (@event.EventType == typeof(EventHandler))
            {
                eventArgsType = typeof(EventArgs);
            }
            else if (!isGeneric || @event.EventType.GetGenericTypeDefinition() != typeof(EventHandler <>))
            {
                throw new ArgumentException(
                          string.Format(CultureInfo.CurrentCulture, Errors.EventIsNotCompatibleWithEventHandler, eventName),
                          "eventName");
            }
            else
            {
#if WINDOWS_PHONE || PORT_45
                eventArgsType = @event.EventType.GetTypeInfo().GenericTypeArguments[0];
#else
                eventArgsType = @event.EventType.GetGenericArguments()[0];
#endif

                Contract.Assume(eventArgsType != null);

#if WINDOWS_PHONE || PORT_45
                var assignable = typeof(EventArgs).GetTypeInfo().IsAssignableFrom(eventArgsType.GetTypeInfo());
#else
                var assignable = typeof(EventArgs).IsAssignableFrom(eventArgsType);
#endif

                if (!assignable)
                {
                    throw new ArgumentException(
                              string.Format(CultureInfo.CurrentCulture, Errors.EventIsNotCompatibleWithEventArgs, eventName),
                              "eventName");
                }
            }

            result = @event.EventRaised(source).Coerce(eventArgsType);

            return(true);
        }