/// <summary>
        /// Creates a Provider based on the specified type.
        /// </summary>
        /// <typeparam name="T">The type of provider to create.</typeparam>
        /// <param name="providerDescriptor">The provider descriptor.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">providerDescriptor</exception>
        /// <exception cref="CreateProviderException">
        /// Error creating provider
        /// </exception>
        protected T CreateProvider <T>(IProviderDescriptor providerDescriptor) where T : IProvider
        {
            try
            {
                if (providerDescriptor == null)
                {
                    throw new ArgumentNullException("providerDescriptor");
                }

                Type type = typeof(T);

                if (!type.IsAssignableFrom(providerDescriptor.ProviderType))
                {
                    throw new CreateProviderException(
                              string.Format("{0} should be assignable from {1}.",
                                            type.Name,
                                            providerDescriptor.ProviderType.Name
                                            ));
                }

                var instance = GenericMethodInvoker.Invoke(
                    this,
                    "Create",
                    providerDescriptor.ProviderType,
                    new object[] { },
                    BindingFlags.NonPublic | BindingFlags.Instance
                    );

                if (instance == null)
                {
                    throw new CreateProviderException(
                              string.Format(
                                  "Could not create instance of type {0}. If you've got a Provider " +
                                  "implementation that exposes constructor arguments then please consider " +
                                  "using any of the existing dependency resolvers or write your " +
                                  "own implementation.",
                                  providerDescriptor.ProviderType.Name));
                }

                var provider = (IProvider)instance;
                provider.Group    = providerDescriptor.ProviderGroup;
                provider.Name     = providerDescriptor.ProviderName;
                provider.Settings = providerDescriptor.ProviderSettings;

                return((T)instance);
            }
            catch (Exception ex)
            {
                if (!(ex is CreateProviderException))
                {
                    throw new CreateProviderException(
                              "Error creating provider.",
                              ex);
                }
                else
                {
                    throw;
                }
            }
        }
 /// <summary>
 /// Gets a setting with the specified name and of the specified type.
 /// </summary>
 /// <param name="settingName">The name of the setting to get.</param>
 /// <param name="type">The type of the setting.</param>
 /// <returns>The setting with the specified name of the specified type</returns>
 public dynamic this[string settingName, Type type]
 {
     get
     {
         return(GenericMethodInvoker.Invoke(this, "Get",
                                            type, new object[] { settingName }));
     }
 }
        /// <summary>
        /// Gets a setting with the specified name and of the specified generic type.
        /// </summary>
        /// <typeparam name="T">The generic type return.</typeparam>
        /// <param name="settingName">The name of the setting to get.</param>
        /// <returns>The setting with the specified name of the specified generic type.</returns>
        public T Get <T>(string settingName)
        {
            if (string.IsNullOrEmpty(settingName))
            {
                throw new ArgumentException("settingName not set.");
            }

            if (!Contains(settingName))
            {
                throw new ArgumentException("settingName does not exist.");
            }

            Type type = typeof(T);

            if (type.IsInterface)
            {
                throw new InvalidOperationException("Type cannot be an interface.");
            }

            var setting = _settings[settingName];

            if (type.IsClass && !type.Equals(typeof(string)))
            {
                // if data parser wasn't set, then attempt to parse
                // setting using the default PipedDataParser
                if (string.IsNullOrEmpty(_dataParserType))
                {
                    try
                    {
                        return(new PipeDelimitedDataParser().Parse <T>(setting));
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidOperationException(
                                  "Could not parse data with the default PipedDataParser," +
                                  "please ensure that you set dataParserType and try again.",
                                  ex);
                    }
                }
                else
                {
                    var parser = (IDataParser)GenericMethodInvoker.Invoke(
                        DependencyResolver.Current,
                        "Resolve",
                        Type.GetType(_dataParserType),
                        new object[] { }
                        );

                    return(parser.Parse <T>(setting));
                }
            }
            else
            {
                return((T)Convert.ChangeType(setting, type));
            }
        }
        public async Task Overload_T_string_string()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 1);
            var mock    = new FooGrain();

            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(bool),
                typeof(bool), typeof(string), typeof(string),
                false, "bar", "foo"
            });

            Assert.Equal(4, result);
        }
        public async Task Overload_Int_String_T()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 1);
            var mock    = new FooGrain();

            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(bool),
                typeof(int), typeof(string), typeof(bool),
                42, "bar", true
            });

            Assert.Equal(3, result);
        }
        public async Task Overload_invoke_with_null()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 2);
            var mock    = new FooGrain();

            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(string[]), typeof(double),
                typeof(string[]), typeof(double),
                null, 0.5d
            });

            Assert.Equal(6, result);
        }
        public async Task Overload_multiple_type_parameters()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 2);
            var mock    = new FooGrain();

            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(string[]), typeof(double),
                typeof(string[]), typeof(double),
                new [] { "a", "b", "c" }, 0.5d
            });

            Assert.Equal(6, result);
        }
        public async Task Overload_object_array_covariant_arg()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 1);
            var mock    = new FooGrain();

            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(bool),
                typeof(string[]),
                new [] { "a", "b", "c" }
            });

            Assert.Equal(5, result);
        }
        public async Task Overload_Int()
        {
            var invoker = new GenericMethodInvoker(typeof(IDummyGrain), "Method", 1);

            var mock = new FooGrain();

            // callsite: mock.Method<bool>(42);
            var result = await invoker.Invoke(mock, new object[]
            {
                typeof(bool),   // type parameter(s)
                typeof(int),    // argument type(s)
                42              // argument(s)
            });

            Assert.Equal(1, result);
        }