/// <summary>
        /// Performs the call to the method defined by a previous <see cref="IMethodCall.Method"/>
        /// call, with the parameters specified by the <see cref="IMethodOperations.AddParameter"/> calls
        /// casting the return value to the specified type.
        /// </summary>
        /// <typeparam name="T">Type of the data returned by the method call</typeparam>
        /// <returns>
        /// The data returned by the method call, casted to the <typeparamref name="T">T type param</typeparamref>
        /// </returns>
        /// <remarks>
        /// The type parameter T must match the type of data returned by the method call
        /// access or an exception will be throw.
        /// </remarks>
        /// <exception cref="InvalidCastException">
        /// If the type parameter T does not match the type of data returned, thus a casting
        /// could not be performed
        /// </exception>
        public T Invoke <T>()
        {
            object retValue;

            object[] args;

            args = InnerParameterBuilder.GetParametersAsArray();

            if (InnerParameterBuilder.Count <= 0)
            {
                try
                {
                    CommonLateBindingOperations.CallOperation(
                        InstanceObject,
                        OperationName,
                        args,
                        out retValue,
                        EOperationType.Method);
                }
                catch
                {
                    throw;
                }
                finally
                {
                    ClearCall();
                }
            }
            else
            {
                ParameterModifier refParams = new ParameterModifier(args.Length);
                for (int i = 0; i < args.Length; ++i)
                {
                    refParams[i] = InnerParameterBuilder.GetReferenceParameterList()[i];
                }

                try
                {
                    CommonLateBindingOperations.CallOperation(
                        InstanceObject,
                        OperationName,
                        args,
                        out retValue,
                        refParams,
                        EOperationType.Method);
                }
                catch
                {
                    throw;
                }
                finally
                {
                    ClearCall();
                }
            }

            LastCallParameters = args;

            return(CommonLateBindingOperations.ComputeReturnType <T>(retValue));
        }
        /// <summary>
        /// Performs a Set operation to modify data
        /// </summary>
        /// <param name="obj">New value </param>
        /// <remarks>
        /// The type of data passed as parameter
        /// must match the type of data we are trying to modify or an
        /// exception will be throw.
        /// </remarks>
        public void Set(object obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException();
            }

            if (OperationName == string.Empty)
            {
                throw new NoOperationNameDefinedException();
            }

            object retVal;

            object[]       args;
            EOperationType op;


            if (OperationType == EGetSetInvokerOperation.Index)
            {
                op = EOperationType.PropertySet;
                List <object> tmp = new List <object>(InnerParameterBuilder.GetParametersAsArray());
                tmp.Add(obj);
                args = tmp.ToArray();
            }
            else
            {
                op = OperationType == EGetSetInvokerOperation.Property ?
                     EOperationType.PropertySet
                         : EOperationType.FieldSet;
                args = new object[] { obj };
            }

            try
            {
                CommonLateBindingOperations.CallOperation(
                    InstanceObject,
                    OperationName,
                    args,
                    out retVal,
                    op);
            }
            catch
            {
                throw;
            }
            finally
            {
                ClearCall();
            }
        }
        /// <summary>
        /// Performs a Get operation to retrieve data, and returns it casted to the specified type.
        /// </summary>
        /// <typeparam name="T">Type of the data accessed</typeparam>
        /// <returns>
        /// The data accessed, casted to the <typeparamref name="T">T type param</typeparamref>
        /// </returns>
        /// <remarks>
        /// The type parameter T must match the type of data we are trying to
        /// access or an exception will be throw.
        /// </remarks>
        /// <exception cref="InvalidCastException">
        /// If the type parameter T does not match the type of data accessed, thus a casting
        /// could not be performed
        /// </exception>
        public T Get <T>()
        {
            if (OperationName == string.Empty)
            {
                throw new NoOperationNameDefinedException();
            }

            object retVal = null;

            object[]       args = null;
            EOperationType op;

            if (OperationType == EGetSetInvokerOperation.Index || InnerParameterBuilder.Count > 0)
            {
                op   = EOperationType.PropertyGet;
                args = InnerParameterBuilder.GetParametersAsArray();
            }
            else
            {
                op = (OperationType == EGetSetInvokerOperation.Property)
                         ?
                     EOperationType.PropertyGet
                         : EOperationType.FieldGet;
            }

            try
            {
                CommonLateBindingOperations.CallOperation(
                    InstanceObject,
                    OperationName,
                    args,
                    out retVal,
                    op);
            }
            catch
            {
                // Sometimes -like when using Office Interop- the index get operation
                // must be treated as a method
                if (OperationType == EGetSetInvokerOperation.Index)
                {
                    op = EOperationType.Method;
                    try
                    {
                        CommonLateBindingOperations.CallOperation(
                            InstanceObject,
                            OperationName,
                            args,
                            out retVal,
                            op);
                    }
                    catch
                    {
                        throw;
                    }
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                ClearCall();
            }
            return(CommonLateBindingOperations.ComputeReturnType <T>(retVal));
        }