public async Task TransferAsync(string sourceName, object sourceConfiguration,
            string sinkName, object sinkConfiguration, ITransferStatistics statistics, CancellationToken cancellation)
        {
            IDataSourceAdapterFactoryAdapter sourceFactoryAdapter;
            if (!sources.TryGetValue(sourceName, out sourceFactoryAdapter))
                throw Errors.UnknownDataSource(sourceName);

            IDataSinkAdapterFactoryAdapter sinkFactoryAdapter;
            if (!sinks.TryGetValue(sinkName, out sinkFactoryAdapter))
                throw Errors.UnknownDataSink(sinkName);

            var context = new DataTransferContext
            {
                SourceName = sourceName,
                SinkName = sinkName
            };

            try
            {
                // Lets start timer now, since factories may take some time as well and we want to capture that
                statistics.Start();

                var source = sourceFactoryAdapter.CreateAsync(sourceConfiguration, context, cancellation);
                var sink = sinkFactoryAdapter.CreateAsync(sinkConfiguration, context, cancellation);

                using (var sourceInstance = await source)
                using (var sinkInstance = await sink)
                    await transferAction.ExecuteAsync(sourceInstance, sinkInstance, statistics, cancellation);
            }
            finally
            {
                statistics.Stop();
            }
        }
        public async Task TransferAsync(string sourceName, object sourceConfiguration,
                                        string sinkName, object sinkConfiguration, ITransferStatistics statistics, CancellationToken cancellation)
        {
            IDataSourceAdapterFactoryAdapter sourceFactoryAdapter;

            if (!sources.TryGetValue(sourceName, out sourceFactoryAdapter))
            {
                throw Errors.UnknownDataSource(sourceName);
            }

            IDataSinkAdapterFactoryAdapter sinkFactoryAdapter;

            if (!sinks.TryGetValue(sinkName, out sinkFactoryAdapter))
            {
                throw Errors.UnknownDataSink(sinkName);
            }

            var context = new DataTransferContext
            {
                SourceName = sourceName,
                SinkName   = sinkName
            };

            try
            {
                // Lets start timer now, since factories may take some time as well and we want to capture that
                statistics.Start();

                var source = sourceFactoryAdapter.CreateAsync(sourceConfiguration, context, cancellation);
                var sink   = sinkFactoryAdapter.CreateAsync(sinkConfiguration, context, cancellation);

                using (var sourceInstance = await source)
                    using (var sinkInstance = await sink)
                        await transferAction.ExecuteAsync(sourceInstance, sinkInstance, statistics, cancellation);
            }
            finally
            {
                statistics.Stop();
            }
        }