public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder == null)
            {
                throw new ArgumentNullException("binder");
            }

            var dynamicObject = Model as RazorDynamicObject;

            if (dynamicObject != null)
            {
                return(dynamicObject.TryGetMember(binder, out result));
            }

            Type modelType = Model.GetType();
            var  prop      = modelType.GetProperty(binder.Name);

            if (prop == null)
            {
                if (!AllowMissingPropertiesOnDynamic)
                {
                    result = null;
                    return(false);
                }

                result = new RazorDynamicObject()
                {
                    AllowMissingPropertiesOnDynamic = AllowMissingPropertiesOnDynamic, Model = new object()
                };
                return(true);
            }

            object value = prop.GetValue(Model, null);

            if (value == null)
            {
                result = value;
                return(true);
            }

            Type valueType = value.GetType();

            result = (CompilerServicesUtility.IsAnonymousType(valueType))
                         ? new RazorDynamicObject {
                Model = value
            }
                         : value;
            return(true);
        }
        /// <summary>
        /// Create a wrapper around an dynamic object.
        /// This wrapper ensures that we can cross the <see cref="AppDomain"/>,
        /// call internal methods (to make Anonymous types work),
        /// or call missing methods (when allowMissingMembers is true).
        /// </summary>
        /// <param name="wrapped">The object to wrap.</param>
        /// <param name="allowMissingMembers">true when we should not throw when missing members are invoked.</param>
        /// <returns>the wrapped object.</returns>
        public static object Create(object wrapped, bool allowMissingMembers = false)
        {
            if (IsWrapped(wrapped))
            {
                return(wrapped);
            }
            var wrapper    = new RazorDynamicObject(wrapped, allowMissingMembers);
            var interfaces =
                wrapped.GetType().GetInterfaces()
                .Where(t => t.IsPublic && t != typeof(IDynamicMetaObjectProvider))
                .Select(MapInterface).ToArray();

            if (interfaces.Length > 0)
            {
                return(Impromptu.DynamicActLike(wrapper, interfaces));
            }
            return(wrapper);
        }
        /// <summary>
        /// Create a wrapper around an dynamic object.
        /// This wrapper ensures that we can cross the <see cref="AppDomain"/>,
        /// call internal methods (to make Anonymous types work),
        /// or call missing methods (when allowMissingMembers is true).
        /// </summary>
        /// <param name="wrapped">The object to wrap.</param>
        /// <param name="allowMissingMembers">true when we should not throw when missing members are invoked.</param>
        /// <returns>the wrapped object.</returns>
        public static object Create(object wrapped, bool allowMissingMembers = false)
        {
            if (IsWrapped(wrapped))
            {
                return(wrapped);
            }
            var wrapper    = new RazorDynamicObject(wrapped, allowMissingMembers);
            var interfaces =
                wrapped.GetType().GetInterfaces()
                // remove IDynamicMetaObjectProvider and ISerializable interfaces because ActLikeProxy does already implement them
                .Where(t => t.IsPublic && t != typeof(IDynamicMetaObjectProvider) && t != typeof(ISerializable))
                .Select(MapInterface).ToArray();

            if (interfaces.Length > 0)
            {
                return(Impromptu.DynamicActLike(wrapper, interfaces));
            }
            return(wrapper);
        }
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder == null)
                throw new ArgumentNullException("binder");

            var dynamicObject = Model as RazorDynamicObject;
            if (dynamicObject != null)
                return dynamicObject.TryGetMember(binder, out result);

            Type modelType = Model.GetType();
            var prop = modelType.GetProperty(binder.Name);
            if (prop == null)
            {
                if (!AllowMissingPropertiesOnDynamic)
                {
                    result = null;
                    return false;
                }

                result = new RazorDynamicObject() { AllowMissingPropertiesOnDynamic = AllowMissingPropertiesOnDynamic, Model = new object() };
                return true;
            }

            object value = prop.GetValue(Model, null);
            if (value == null)
            {
                result = value;
                return true;
            }

            Type valueType = value.GetType();

            result = (CompilerServicesUtility.IsAnonymousType(valueType))
                         ? new RazorDynamicObject { Model = value }
                         : value;
            return true;
        }
            /// <summary>
            /// Tries to find a member with the given name, the given arguments
            /// and the given parameter types and invokes that member.
            /// </summary>
            /// <param name="typeToSearch">the type we search for that member.</param>
            /// <param name="name">the name of the member</param>
            /// <param name="args">the arguments of the member</param>
            /// <param name="paramTypes">the type of the arguments of the member</param>
            /// <param name="result">the result of invoking the found member.</param>
            /// <returns>true if a member was found and invoked.</returns>
            private bool TryFindInvokeMember(Type typeToSearch, string name, object[] args, Type[] paramTypes, out object result)
            {
                var members = typeToSearch.GetMember(name, RazorDynamicObject.Flags);
                var found   = false;

                result = null;
                foreach (var member in members)
                {
                    var methodInfo = member as MethodInfo;
                    if (!found && methodInfo != null && RazorDynamicObject.CompatibleWith(methodInfo.GetParameters(), paramTypes))
                    {
                        result = methodInfo.Invoke(_component, args);
                        found  = true;
                        break;
                    }
                    var property = member as PropertyInfo;
                    if (!found && property != null)
                    {
                        var setMethod = property.GetSetMethod(true);
                        if (setMethod != null && RazorDynamicObject.CompatibleWith(setMethod.GetParameters(), paramTypes))
                        {
                            result = setMethod.Invoke(_component, args);
                            found  = true;
                            break;
                        }
                        var getMethod = property.GetGetMethod(true);
                        if (getMethod != null && RazorDynamicObject.CompatibleWith(getMethod.GetParameters(), paramTypes))
                        {
                            result = getMethod.Invoke(_component, args);
                            found  = true;
                            break;
                        }
                    }
                }
                return(found);
            }
            public object GetResult(Invocation invocation)
            {
                (new PermissionSet(PermissionState.Unrestricted)).Assert();
                object result = null;
                string name   = invocation.Name.Name;

                object[] args       = invocation.Args;
                Type[]   paramTypes = args.Select(o => o.GetType()).ToArray();
                try
                {
                    if (invocation.Kind == InvocationKind.NotSet && invocation.Name.Name == "_BinaryOperator")
                    { // We use that for operators
                        var    exp   = (ExpressionType)args[0];
                        object other = args[1];
                        result = Impromptu.InvokeBinaryOperator(_component, exp, other);
                    }
                    else if (invocation.Kind == InvocationKind.NotSet && invocation.Name.Name == "_UnaryOperator")
                    { // We use that for operators
                        var exp = (ExpressionType)args[0];
                        result = Impromptu.InvokeUnaryOperator(exp, _component);
                    }
                    else
                    {
                        // First we try to resolve via DLR
                        dynamic target = _component;
                        result = invocation.InvokeWithStoredArgs(_component);
                    }
                }
                catch (RuntimeBinderException)
                {
                    // DLR doesn't like some kind of functions,
                    // expecially because we have casted the component to object...
                    bool found = false;
                    switch (invocation.Kind)
                    {
                    case InvocationKind.Convert:
                        var  targetType = (Type)args[0];
                        bool tExplict   = false;
                        if (args.Length == 2)
                        {
                            tExplict = (bool)args[1];
                        }
                        // try to find explicit or implicit operator.
                        try
                        {
                            result = DynamicCast(_component, targetType);
                            found  = true;
                        }
                        catch (Exception)
                        {
                            found = false;
                        }
                        break;

                    //case InvocationKind.IsEvent:
                    //case InvocationKind.AddAssign:
                    //case InvocationKind.SubtractAssign:
                    //case InvocationKind.Invoke:
                    //case InvocationKind.InvokeAction:
                    //case InvocationKind.InvokeUnknown:
                    //case InvocationKind.InvokeMember: // TODO: add testcase
                    //case InvocationKind.InvokeMemberAction: // TODO: add testcase
                    //case InvocationKind.GetIndex: // TODO: add testcase
                    //case InvocationKind.SetIndex: // TODO: add testcase
                    case InvocationKind.Get:
                    case InvocationKind.Set:
                    case InvocationKind.InvokeMemberUnknown:
                    {
                        if (!found)
                        {
                            if (!TryFindInvokeMember(_runtimeType, name, args, paramTypes, out result))
                            {
                                // search all interfaces as well
                                foreach (var @interface in _runtimeType.GetInterfaces().Where(i => i.IsPublic))
                                {
                                    if (TryFindInvokeMember(@interface, name, args, paramTypes, out result))
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                found = true;
                            }
                        }
                    }
                    break;

                    default:
                        break;
                    }

                    if (!found)
                    {
                        if (_allowMissing)
                        {
                            return(RazorDynamicObject.Create("", _allowMissing));
                        }
                        throw;
                    }
                }
                if (RazorDynamicObject.IsPrimitive(result))
                {
                    return(result);
                }
                else
                {
                    return(RazorDynamicObject.Create(result, _allowMissing));
                }
            }