/// <summary> /// /// </summary> /// <param name="clientBuilder"></param> /// <param name="accessMethod"></param> /// <param name="tokenEndpoint"></param> /// <param name="clientId"></param> /// <param name="clientSecret"></param> /// <param name="tokenStore"></param> /// <returns></returns> public static void AddOAuth( this IHttpClientBuilder clientBuilder, AccessMethod accessMethod, string tokenEndpoint, string clientId, string clientSecret, ITokenStore tokenStore) { clientBuilder.AddOAuth( accessMethod.Name, tokenEndpoint, clientId, clientSecret, tokenStore); }
internal static IHttpClientBuilder AddTypedClientCore <TClient>(this IHttpClientBuilder builder, Func <HttpClient, TClient> factory, bool validateSingleType) where TClient : class { ReserveClient(builder, typeof(TClient), builder.Name, validateSingleType); builder.Services.AddTransient <TClient>(s => { IHttpClientFactory httpClientFactory = s.GetRequiredService <IHttpClientFactory>(); HttpClient httpClient = httpClientFactory.CreateClient(builder.Name); return(factory(httpClient)); }); return(builder); }
/// <summary> /// Sets the length of time that a <see cref="HttpMessageHandler"/> instance can be reused. Each named /// client can have its own configured handler lifetime value. The default value is two minutes. Set the lifetime to /// <see cref="Timeout.InfiniteTimeSpan"/> to disable handler expiry. /// </summary> /// <remarks> /// <para> /// The default implementation of <see cref="IHttpClientFactory"/> will pool the <see cref="HttpMessageHandler"/> /// instances created by the factory to reduce resource consumption. This setting configures the amount of time /// a handler can be pooled before it is scheduled for removal from the pool and disposal. /// </para> /// <para> /// Pooling of handlers is desirable as each handler typically manages its own underlying HTTP connections; creating /// more handlers than necessary can result in connection delays. Some handlers also keep connections open indefinitely /// which can prevent the handler from reacting to DNS changes. The value of <paramref name="handlerLifetime"/> should be /// chosen with an understanding of the application's requirement to respond to changes in the network environment. /// </para> /// <para> /// Expiry of a handler will not immediately dispose the handler. An expired handler is placed in a separate pool /// which is processed at intervals to dispose handlers only when they become unreachable. Using long-lived /// <see cref="HttpClient"/> instances will prevent the underlying <see cref="HttpMessageHandler"/> from being /// disposed until all references are garbage-collected. /// </para> /// </remarks> public static IHttpClientBuilder SetHandlerLifetime(this IHttpClientBuilder builder, TimeSpan handlerLifetime) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (handlerLifetime != Timeout.InfiniteTimeSpan && handlerLifetime < HttpClientFactoryOptions.MinimumHandlerLifetime) { throw new ArgumentException(SR.HandlerLifetime_InvalidValue, nameof(handlerLifetime)); } builder.Services.Configure <HttpClientFactoryOptions>(builder.Name, options => options.HandlerLifetime = handlerLifetime); return(builder); }
/// <summary> /// Configures a binding between the <typeparamref name="TClient" /> type and the named <see cref="HttpClient"/> /// associated with the <see cref="IHttpClientBuilder"/>. /// </summary> /// <typeparam name="TClient"> /// The type of the typed client. They type specified will be registered in the service collection as /// a transient service. /// </typeparam> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="factory">A factory function that will be used to construct the typed client.</param> /// <remarks> /// <para> /// <typeparamref name="TClient"/> instances constructed with the appropriate <see cref="HttpClient" /> /// can be retrieved from <see cref="IServiceProvider.GetService(Type)" /> (and related methods) by providing /// <typeparamref name="TClient"/> as the service type. /// </para> /// <para> /// Calling <see cref="HttpClientBuilderExtensions.AddTypedClient{TClient}(IHttpClientBuilder,Func{HttpClient,IServiceProvider,TClient})"/> /// will register a typed client binding that creates <typeparamref name="TClient"/> using the provided factory function. /// </para> /// </remarks> public static IHttpClientBuilder AddTypedClient <TClient>(this IHttpClientBuilder builder, Func <HttpClient, IServiceProvider, TClient> factory) where TClient : class { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (factory == null) { throw new ArgumentNullException(nameof(factory)); } return(AddTypedClientCore <TClient>(builder, factory, validateSingleType: false)); }
public static IHttpClientBuilder WithProxy(this IHttpClientBuilder builder, IWebProxy proxy) { if (proxy == null) { return(builder); } builder.Services.Configure <HttpClientConfig>(config => { config.UseProxy = true; config.Proxy = proxy; }); return(builder); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a <see cref="Policy"/> /// created by executing the provided configuration delegate. The policy builder will be preconfigured to trigger /// application of the policy for requests that fail with a connection or server error (5XX status code). /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="configurePolicy">A delegate used to create a <see cref="IAsyncPolicy{HttpResponseMessage}"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// <para> /// The <see cref="PolicyBuilder{HttpResponseMessage}"/> provided to <paramref name="configurePolicy"/> has been /// preconfigured to handle connection errors (as <see cref="HttpRequestException"/>) or server errors (as a 5XX HTTP /// status code). The configuration is similar to the following code sample: /// <code> /// Policy.HandleAsync<HttpRequestException>().OrResult<HttpResponseMessage>(response => /// { /// return response.StatusCode >= HttpStatusCode.InternalServerError; /// } /// </code> /// </para> /// <para> /// The policy created by <paramref name="configurePolicy"/> will be cached indefinitely per named client. Policies /// are generally designed to act as singletons, and can be shared when appropriate. To share a policy across multiple /// named clients, first create the policy and the pass it to multiple calls to /// <see cref="AddPolicyHandler(IHttpClientBuilder, IAsyncPolicy)"/> or /// <see cref="AddPolicyHandler(IHttpClientBuilder, IAsyncPolicy{HttpResponseMessage})"/> as desired. /// </para> /// </remarks> public static IHttpClientBuilder AddServerErrorPolicyHandler( this IHttpClientBuilder builder, Func <PolicyBuilder <HttpResponseMessage>, IAsyncPolicy <HttpResponseMessage> > configurePolicy) { var policyBuilder = Policy.Handle <HttpRequestException>().OrResult <HttpResponseMessage>(response => { return(response.StatusCode >= HttpStatusCode.InternalServerError); }); // Important - cache policy instances so that they are singletons per handler. var policy = configurePolicy(policyBuilder); builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(policy)); return(builder); }
public static IHttpClientBuilder AddPolicyHandlers(this IHttpClientBuilder httpClientBuilder, string policySectionName, ILoggerFactory loggerFactory, IConfiguration configuration) { var retryLogger = loggerFactory.CreateLogger("PollyHttpRetryPoliciesLogger"); var circuitBreakerLogger = loggerFactory.CreateLogger("PollyHttpCircuitBreakerPoliciesLogger"); var policyConfig = new PolicyConfig(); configuration.Bind(policySectionName, policyConfig); var circuitBreakerPolicyConfig = (ICircuitBreakerPolicyConfig)policyConfig; var retryPolicyConfig = (IRetryPolicyConfig)policyConfig; return(httpClientBuilder.AddRetryPolicyHandler(retryLogger, retryPolicyConfig) .AddCircuitBreakerHandler(circuitBreakerLogger, circuitBreakerPolicyConfig)); }
/// <summary> /// Adds an additional message handler from the dependency injection container for a named <see cref="HttpClient"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <typeparam name="THandler"> /// The type of the <see cref="DelegatingHandler"/>. The handler type must be registered as a transient service. /// </typeparam> /// <remarks> /// <para> /// The <typeparamref name="THandler"/> will be resolved from a scoped service provider that shares /// the lifetime of the handler being constructed. /// </para> /// </remarks> public static IHttpClientBuilder AddHttpMessageHandler <THandler>(this IHttpClientBuilder builder) where THandler : DelegatingHandler { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.Configure <HttpClientFactoryOptions>(builder.Name, options => { options.HttpMessageHandlerBuilderActions.Add(b => b.AdditionalHandlers.Add(b.Services.GetRequiredService <THandler>())); }); return(builder); }
private static IHttpClientBuilder AddCircuitBreakerPolicy(this IHttpClientBuilder httpClientBuilder, CircuitBreakerPolicyOptions options) { return(httpClientBuilder.AddPolicyHandler( HttpPolicyExtensions.HandleTransientHttpError() .Or <TimeoutRejectedException>() .Or <HttpRequestException>() .OrResult(m => m.StatusCode == HttpStatusCode.TooManyRequests) .CircuitBreakerAsync( options.HandledEventsAllowedBeforeBreaking, TimeSpan.FromSeconds(options.DurationOfBreakSeconds), options.OnBreak, options.OnReset, options.OnHalfOpen))); }
/// <summary> /// Adds an additional interceptor from the dependency injection container for a gRPC client. /// </summary> /// <typeparam name="TInterceptor">The type of the <see cref="Interceptor"/>.</typeparam> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> public static IHttpClientBuilder AddInterceptor <TInterceptor>(this IHttpClientBuilder builder) where TInterceptor : Interceptor { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddInterceptor(serviceProvider => { return(serviceProvider.GetRequiredService <TInterceptor>()); }); return(builder); }
/// <summary> /// Adds a delegate that will be used to configure a named <see cref="HttpClient"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="configureClient">A delegate that is used to configure an <see cref="HttpClient"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// The <see cref="IServiceProvider"/> provided to <paramref name="configureClient"/> will be the /// same application's root service provider instance. /// </remarks> public static IHttpClientBuilder ConfigureHttpClient(this IHttpClientBuilder builder, Action <IServiceProvider, HttpClient> configureClient) { ThrowHelper.ThrowIfNull(builder); ThrowHelper.ThrowIfNull(configureClient); builder.Services.AddTransient <IConfigureOptions <HttpClientFactoryOptions> >(services => { return(new ConfigureNamedOptions <HttpClientFactoryOptions>(builder.Name, (options) => { options.HttpClientActions.Add(client => configureClient(services, client)); })); }); return(builder); }
/// <summary> /// Adds a named Microsoft Identity application authentication message handler initialized with delegates. /// </summary> /// <param name="builder">Builder.</param> /// <param name="serviceName">Name of the configuration for the service.</param> /// <param name="configureOptions">Action to configure the options.</param> /// <returns>The builder for chaining.</returns> public static IHttpClientBuilder AddMicrosoftIdentityAppAuthenticationHandler( this IHttpClientBuilder builder, string serviceName, Action <MicrosoftIdentityAuthenticationMessageHandlerOptions> configureOptions) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.Configure(serviceName, configureOptions); builder.AddMicrosoftIdentityAuthenticationHandlerCore(factory => factory.CreateAppHandler(serviceName)); return(builder); }
public static IHttpClientBuilder AllowSelfSignedCertificate(this IHttpClientBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } return(builder.ConfigureHttpMessageHandlerBuilder(b => { b.PrimaryHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }; })); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with the provided /// <see cref="IAsyncPolicy{HttpResponseMessage}"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policy">The <see cref="IAsyncPolicy{HttpResponseMessage}"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandler(this IHttpClientBuilder builder, IAsyncPolicy <HttpResponseMessage> policy) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(policy)); return(builder); }
public static IHttpClientBuilder AddAuthentication(this IHttpClientBuilder builder, Func <IServiceProvider, ClientCredentials> credentialsProvider, Func <IServiceProvider, string> identityAuthorityProvider) { builder.Services.TryAddSingleton <AccessTokensCacheManager>(); builder.AddHttpMessageHandler(provider => { var credentials = credentialsProvider.Invoke(provider); var identityAuthority = identityAuthorityProvider.Invoke(provider); return(CreateDelegatingHandler(provider, credentials, identityAuthority)); }); return(builder); }
public static IHttpClientBuilder WithProxy(this IHttpClientBuilder builder, string proxyUrl) { if (string.IsNullOrEmpty(proxyUrl)) { return(builder); } builder.Services.Configure <HttpClientConfig>(config => { config.UseProxy = true; config.Proxy = new WebProxy(proxyUrl); }); return(builder); }
public static IHttpClientBuilder GenerateCorrelationId(this IHttpClientBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.ConfigureHttpClient((sp, client) => { var correlationIdOptions = sp.GetRequiredService <IOptions <CorrelationIdOptions> >().Value; var correlationIdProvider = sp.GetRequiredService <ICorrelationIdProvider>(); client.DefaultRequestHeaders.Add(correlationIdOptions.RequestHeader, correlationIdProvider.GenerateCorrelationId(null)); }); return(builder); }
public static IHttpClientBuilder AddLCUTimeoutPolicy(this IHttpClientBuilder httpClientBuilder, IPolicyRegistry <string> registry) { return(httpClientBuilder .AddPolicyHandler(request => { var timeoutPolicy = "regular"; if (request.Method != HttpMethod.Get) { timeoutPolicy = "long"; } return registry.Get <IAsyncPolicy <HttpResponseMessage> >(timeoutPolicy); })); }
/// <summary> /// Removes <typeparamref name="THandler" /> from http message handling pipeline. /// </summary> public static IHttpClientBuilder RemoveHttpMessageHandler <THandler>(this IHttpClientBuilder builder) where THandler : DelegatingHandler { builder.Services.Configure <HttpClientFactoryOptions>(builder.Name, options => { options.HttpMessageHandlerBuilderActions.Add(b => { var handlers = b.AdditionalHandlers.Where(x => x is THandler).ToArray(); foreach (var handler in handlers) { b.AdditionalHandlers.Remove(handler); } }); }); return(builder); }
public Client(IDIContainer container, IConfiguration configuration, IHttpClientBuilder clientBuilder, ILog log, ISerializer serializer, ICache cache, CancellationToken?defaultCancellationToken = null, IProgress <ISDKProgress> defaultProgress = null) { Configuration = configuration; _container = container; _clientBuilder = clientBuilder; if (defaultCancellationToken != null) { DefaultCancellationToken = defaultCancellationToken.Value; } DefaultProgress = defaultProgress; _log = log; _serializer = serializer; _cache = cache; }
public static IHttpClientBuilder AddPolicyHandlers(this IHttpClientBuilder httpClientBuilder, string policySectionName, IConfiguration configuration) { var serviceProvider = httpClientBuilder.Services.BuildServiceProvider(); var retryLogger = serviceProvider.GetService <ILogger <HttpRetryPolicies> >(); var circuitBreakerLogger = serviceProvider.GetService <ILogger <HttpCircuitBreakerPolicies> >(); var policyConfig = new PolicyConfig(); configuration.Bind(policySectionName, policyConfig); var circuitBreakerPolicyConfig = (ICircuitBreakerPolicyConfig)policyConfig; var retryPolicyConfig = (IRetryPolicyConfig)policyConfig; return(httpClientBuilder.AddRetryPolicyHandler(retryLogger, retryPolicyConfig) .AddCircuitBreakerHandler(circuitBreakerLogger, circuitBreakerPolicyConfig)); }
/// <summary>Add SimpleS3 services to a service collection.</summary> /// <param name="collection">The service collection</param> public static IS3ClientBuilder AddSimpleS3(this IServiceCollection collection) { S3ClientBuilder builder = new S3ClientBuilder(collection); ICoreBuilder clientBuilder = collection.AddSimpleS3Core(); clientBuilder.UseS3Client(); builder.CoreBuilder = clientBuilder; IHttpClientBuilder httpBuilder = clientBuilder.UseHttpClientFactory(); httpBuilder.UseDefaultHttpPolicy(); builder.HttpBuilder = httpBuilder; return(builder); }
public static void AddExponentialBackoff(this IHttpClientBuilder client, int retryCount, int retryInterval = 0, bool retryForever = false) { if (client == null) { throw new ArgumentNullException(nameof(client)); } client.AddInterceptor(services => { var interceptor = services.GetRequiredService <ExponentialBackoffInterceptor>(); interceptor.RetryCount = retryCount; interceptor.RetryInterval = retryInterval; interceptor.RetryForever = retryForever; return(interceptor); }); }
/// <summary> /// Adds the retry handler. /// </summary> /// <param name="builder">The builder.</param> /// <param name="retryPolicyOptions">The retry policy options.</param> /// <returns>IHttpClientBuilder.</returns> /// <exception cref="System.ArgumentNullException">builder</exception> /// <exception cref="System.ArgumentNullException">retryPolicyOptions</exception> public static IHttpClientBuilder AddRetryHandler(this IHttpClientBuilder builder, HttpRetryPolicyOptions retryPolicyOptions) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (retryPolicyOptions == null) { throw new ArgumentNullException(nameof(retryPolicyOptions)); } builder.AddHttpMessageHandler(() => new RetryDelegatingHandler(retryPolicyOptions)); return(builder); }
public static IHttpClientBuilder WithProxy(this IHttpClientBuilder httpClientBuilder, bool bypassSslCheck = true) { httpClientBuilder.ConfigurePrimaryHttpMessageHandler(() => { var handler = new HttpClientHandler(); if (bypassSslCheck) { handler.ServerCertificateCustomValidationCallback = (message, certificate2, chain, errors) => true; } return(handler); }); return(httpClientBuilder); }
/// <summary> /// Adds a delegate that will be used to configure a named <see cref="HttpClient"/>. /// </summary> /// <param name="builder">The <see cref="IServiceCollection"/>.</param> /// <param name="configureClient">A delegate that is used to configure an <see cref="HttpClient"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> public static IHttpClientBuilder AddHttpClientOptions(this IHttpClientBuilder builder, Action <HttpClient> configureClient) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configureClient == null) { throw new ArgumentNullException(nameof(configureClient)); } builder.Services.Configure <HttpClientFactoryOptions>(builder.Name, options => options.HttpClientActions.Add(configureClient)); return(builder); }
public static IHttpClientBuilder AddClientCertificate(this IHttpClientBuilder httpClientBuilder, X509Certificate2 certificate) { httpClientBuilder.ConfigureHttpMessageHandlerBuilder(builder => { if (builder.PrimaryHandler is HttpClientHandler handler) { handler.AddClientCertificate(certificate); } else { throw new InvalidOperationException($"Only {typeof(HttpClientHandler).FullName} handler type is supported. Actual type: {builder.PrimaryHandler.GetType().FullName}"); } }); return(httpClientBuilder); }
private static void RegisterAgentType <T>(IServiceCollection services, ServiceAgentSettings settings, Action <IServiceProvider, HttpClient> clientCreatedAction, Action <string, IHttpClientBuilder> clientBuiltAction) where T : class { // the type specified will be registered in the service collection as a transient service IHttpClientBuilder builder = services.AddHttpClient <T>(typeof(T).Name).ConfigureHttpClient((serviceProvider, client) => { var serviceSettings = settings.GetServiceSettings(typeof(T).Name); ConfigureHttpClient(serviceProvider, client, serviceSettings, clientCreatedAction); }); // invoke additional actions for HttpClientBuilder ex. attaching DelegatingHandlers clientBuiltAction?.Invoke(typeof(T).Name, builder); }
/// <summary> /// Adds a delegate that will be used to configure message handlers using <see cref="HttpMessageHandlerBuilder"/> /// for a named <see cref="HttpClient"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="configureBuilder">A delegate that is used to configure an <see cref="HttpMessageHandlerBuilder"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> public static IHttpClientBuilder ConfigureHttpMessageHandlerBuilder(this IHttpClientBuilder builder, Action <HttpMessageHandlerBuilder> configureBuilder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configureBuilder == null) { throw new ArgumentNullException(nameof(configureBuilder)); } builder.Services.Configure <HttpClientFactoryOptions>(builder.Name, options => options.HttpMessageHandlerBuilderActions.Add(configureBuilder)); return(builder); }
public static IHttpClientBuilder AddNaosMessageHandlers(this IHttpClientBuilder builder, Action <IHttpClientBuilder> setupAction = null) { if (setupAction != null) { setupAction.Invoke(builder); return(builder); } else { // default handlers return(builder .AddHttpMessageHandler <HttpClientCorrelationHandler>() .AddHttpMessageHandler <HttpClientServiceContextHandler>() .AddHttpMessageHandler <HttpClientLogHandler>()); } }
public void Generate(PropertyWithName pwn, String baseSaveFolder, RunConfig config) { TestBuilder = config.TestBuilder; HttpBuilder = config.HttpBuilder; var sf = Path.Combine(baseSaveFolder, config.Directory.ReplaceKeys(pwn, config)); if (!Directory.Exists(sf)) { Directory.CreateDirectory(sf); } var syntax = internalGenerate(pwn.PropertyName, pwn.Type).NormalizeWhitespace("\t", true); var file = Path.Combine(sf, config.FileName.ReplaceKeys(pwn, config)); if (File.Exists(file)) { File.Delete(file); } using (StreamWriter writer = new StreamWriter(File.OpenWrite(file))) { syntax.WriteTo(writer); //formattedNode.WriteTo(writer); } }
public void Generate(IList<PropertyWithName> props, string baseSaveDirectory, RunConfig config) { var dir = Path.Combine(baseSaveDirectory, config.Directory); if(!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } clientBuilder = config.HttpBuilder; taskBuilder = config.TaskBuilder; testBuilder = config.TestBuilder; variables = config.Variables; var cu = CompilationUnit(); cu = cu.AddUsing("System").WithLeadingTrivia(GeneratorBase.GetLicenseComment()); cu = cu.AddUsings(new string[] { "System.Threading.Tasks", "Newtonsoft.Json", "Newtonsoft.Json.Linq" }); cu = cu.AddUsings(clientBuilder.Namespace); cu = cu.AddUsings(testBuilder.Namespaces); if(String.Compare(variables.GetValue("IsUWP"), "1", true) == 0) { cu = cu.AddUsing("System.Runtime.InteropServices"); } var namesp = NamespaceDeclaration(IdentifierName("Sannel.House.ServerSDK.Tests")); var @class = ClassDeclaration("ServerContextTests") .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword)); foreach(var prop in props) { @class = addType(prop, @class); } namesp = namesp.AddMembers(@class); cu = cu.AddMembers(namesp).NormalizeWhitespace("\t", true); using(var writer = new StreamWriter(File.OpenWrite(Path.Combine(dir, config.FileName)))) { cu.WriteTo(writer); } }