The factory
The factory INTERFACE
The factory is the public face of your connection: it names the venue, declares which credentials the host should collect, and turns those credentials into a live provider.
What the factory is
IDataProviderFactory exists so the host can describe your provider before any
credentials are entered. It carries a stable Key that identifies the venue across sessions,
a DisplayName for the provider list, and a list of RequiredCredentials that the
host turns directly into a form. Nothing connects yet — the factory is pure metadata plus one
construction method.
IDataProviderFactory.csusing System.Collections.Generic;
namespace TradeStrike.Pipeline.Providers;
public interface IDataProviderFactory
{
// Stable lower-case id, e.g. "polygon". Matches IDataProvider.Key.
string Key { get; }
// Shown in the host's provider list.
string DisplayName { get; }
// Fields the host must collect before Create can be called. Ordered for UI display.
IReadOnlyList<ProviderCredentialField> RequiredCredentials { get; }
// Validate + construct. The provider starts Disconnected; the host calls
// ConnectAsync to bring it online. Throws ArgumentException on a missing/empty
// required field.
IDataProvider Create(IReadOnlyDictionary<string, string> credentials);
}
Declaring credential fields
Each ProviderCredentialField describes one input row. Kind drives how the host
renders it — a Secret field is masked, a Url field validates shape, a
Toggle becomes a checkbox — while Placeholder and Required
tune the editor. Keep each field's Key stable, because it doubles as the dictionary key you
read back in Create.
ProviderCredentialField.csnamespace TradeStrike.Pipeline.Providers;
public sealed record ProviderCredentialField(
string Key,
string DisplayName,
ProviderCredentialKind Kind,
string? Placeholder = null,
bool Required = true);
public enum ProviderCredentialKind
{
Plain, // free-text box
Secret, // masked (password / API secret)
Choice, // single-choice from a fixed list
Toggle, // boolean checkbox
Url, // URL field, rendered with URL validation
}
Creating the provider
When the user submits the form, the host calls Create(credentials) with the collected
values as a IReadOnlyDictionary<string, string> keyed by each field's Key.
This is the right place to validate — a missing API key or a malformed URL should throw
ArgumentException here, so the failure surfaces in the credentials dialog rather than later
during a connection attempt. The contract requires you to reject every empty
Required field before constructing. On success you return a fully constructed, still
disconnected IDataProvider; the host calls
ConnectAsync afterwards.
PolygonDataFactory.csusing System;
using System.Collections.Generic;
using TradeStrike.Pipeline.Providers;
public sealed class PolygonDataFactory : IDataProviderFactory
{
public string Key => "polygon";
public string DisplayName => "Polygon.io";
public IReadOnlyList<ProviderCredentialField> RequiredCredentials => new[]
{
new ProviderCredentialField("ApiKey", "API key", ProviderCredentialKind.Secret),
new ProviderCredentialField("BaseUrl", "Base URL", ProviderCredentialKind.Url,
Placeholder: "https://api.polygon.io", Required: false),
};
public IDataProvider Create(IReadOnlyDictionary<string, string> credentials)
{
// Validate every Required field BEFORE constructing — the contract.
if (!credentials.TryGetValue("ApiKey", out var apiKey) || string.IsNullOrWhiteSpace(apiKey))
throw new ArgumentException("ApiKey is required.", nameof(credentials));
credentials.TryGetValue("BaseUrl", out var baseUrl); // optional
return new PolygonDataProvider(apiKey, baseUrl ?? "https://api.polygon.io");
}
}
Key and the provider's
Key must match (here, "polygon"). The host uses it as the registry key, and as
the prefix when building fully-qualified instrument identifiers across providers (the host's convention,
e.g. "polygon:AAPL").