Commit 14aada21 authored by Savorboard's avatar Savorboard

refactor options configuration moudle.

parent a6beba97
......@@ -2,24 +2,13 @@
using System.Collections.Generic;
using System.Text;
namespace DotNetCore.CAP.EntityFrameworkCore
namespace DotNetCore.CAP
{
public class EFOptions
{
public const string DefaultSchema = "cap";
public const string DefaultMigrationsHistoryTableName = "__EFMigrationsHistory";
public EFOptions()
{
ConnectionString = "Server=DESKTOP-M9R8T31;Initial Catalog=Test;User Id=sa;Password=P@ssw0rd;MultipleActiveResultSets=True";
}
/// <summary>
/// Gets or sets the database's connection string that will be used to store database entities.
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// Gets or sets the schema to use when creating database objects.
/// Default is <see cref="DefaultSchema"/>.
......@@ -37,25 +26,7 @@ namespace DotNetCore.CAP.EntityFrameworkCore
/// Default is <see cref="DefaultMigrationsHistoryTableName"/>.
/// </summary>
public string MigrationsHistoryTableName { get; set; } = DefaultMigrationsHistoryTableName;
}
//public static class CapOptionsExtensions
//{
// public static EFOptions UseSqlServer(this CapOptions options, string connectionString)
// {
// return options.UseSqlServer(opts =>
// {
// opts.ConnectionString = connectionString;
// });
// }
// public static EFOptions UseSqlServer(this CapOptions options, Action<SqlServerOptions> configure)
// {
// if (configure == null) throw new ArgumentNullException(nameof(configure));
// (new EFOptions(configure));
// return options;
// }
//}
public Type DbContextType { get; internal set; }
}
}
using System;
using DotNetCore.CAP;
using Microsoft.EntityFrameworkCore;
namespace Microsoft.Extensions.DependencyInjection
{
public static class CapOptionsExtensions
{
public static CapOptions UseSqlServer(this CapOptions options, string connectionString)
{
return options.UseSqlServer(opt =>
{
opt.ConnectionString = connectionString;
});
}
public static CapOptions UseSqlServer(this CapOptions options, Action<SqlServerOptions> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
options.RegisterExtension(new SqlServerCapOptionsExtension(configure));
return options;
}
public static CapOptions UseEntityFramework<TContext>(this CapOptions options)
where TContext : DbContext
{
return options.UseEntityFramework<TContext>(opt =>
{
opt.DbContextType = typeof(TContext);
});
}
public static CapOptions UseEntityFramework<TContext>(this CapOptions options, Action<EFOptions> configure)
where TContext : DbContext
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
var efOptions = new EFOptions { DbContextType = typeof(TContext) };
configure(efOptions);
options.RegisterExtension(new SqlServerCapOptionsExtension(configure));
return options;
}
}
}
using System;
using DotNetCore.CAP;
using Microsoft.EntityFrameworkCore;
using DotNetCore.CAP.EntityFrameworkCore;
using DotNetCore.CAP.Processor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.DependencyInjection
namespace DotNetCore.CAP
{
/// <summary>
/// Contains extension methods to <see cref="CapBuilder"/> for adding entity framework stores.
/// </summary>
public static class CapEntityFrameworkBuilderExtensions
public class SqlServerCapOptionsExtension : ICapOptionsExtension
{
/// <summary>
/// Adds an Entity Framework implementation of message stores.
/// </summary>
public static CapBuilder AddEntityFrameworkStores<TContext>(this CapBuilder builder, Action<SqlServerOptions> actionOptions)
where TContext : DbContext
private Action<SqlServerOptions> _configure;
public SqlServerCapOptionsExtension(Action<SqlServerOptions> configure)
{
//builder.Services.AddScoped<ICapMessageStore, CapMessageStore<TContext>>();
_configure = configure;
}
builder.Services.AddSingleton<IStorage, EFStorage>();
builder.Services.AddScoped<IStorageConnection, EFStorageConnection>();
public void AddServices(IServiceCollection services)
{
services.AddSingleton<IStorage, EFStorage>();
services.AddScoped<IStorageConnection, EFStorageConnection>();
services.AddScoped<ICapPublisher, CapPublisher>();
services.AddTransient<IAdditionalProcessor, DefaultAdditionalProcessor>();
builder.Services.AddScoped<ICapPublisher, CapPublisher>();
services.Configure(_configure);
builder.Services.AddTransient<IAdditionalProcessor, DefaultAdditionalProcessor>();
builder.Services.Configure(actionOptions);
var sqlServerOptions = new SqlServerOptions();
sqlServerOptions.DbContextType = typeof(TContext);
actionOptions(sqlServerOptions);
builder.Services.AddSingleton(sqlServerOptions);
_configure(sqlServerOptions);
services.AddSingleton(sqlServerOptions);
builder.Services.AddDbContext<CapDbContext>(options =>
services.AddDbContext<CapDbContext>(options =>
{
options.UseSqlServer(sqlServerOptions.ConnectionString, sqlOpts =>
{
......@@ -43,10 +37,6 @@ namespace Microsoft.Extensions.DependencyInjection
sqlServerOptions.MigrationsHistoryTableSchema ?? sqlServerOptions.Schema);
});
});
return builder;
}
}
}
\ No newline at end of file
}
using System;
using System.Collections.Generic;
using System.Text;
using DotNetCore.CAP.EntityFrameworkCore;
namespace DotNetCore.CAP
{
public class SqlServerOptions : EFOptions
{
/// <summary>
/// Gets or sets the database's connection string that will be used to store database entities.
/// </summary>
public string ConnectionString { get; set; } //= "Server=DESKTOP-M9R8T31;Initial Catalog=Test;User Id=sa;Password=P@ssw0rd;MultipleActiveResultSets=True";
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetCore.CAP.EntityFrameworkCore
{
public class SqlServerOptions
{
public const string DefaultSchema = "cap";
public const string DefaultMigrationsHistoryTableName = "__EFMigrationsHistory";
/// <summary>
/// Gets or sets the database's connection string that will be used to store database entities.
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// Gets or sets the schema to use when creating database objects.
/// Default is <see cref="DefaultSchema"/>.
/// </summary>
public string Schema { get; set; } = DefaultSchema;
/// <summary>
/// Gets or sets the migrations history table's schema.
/// If this is null, <see cref="Schema"/> will be used.
/// </summary>
public string MigrationsHistoryTableSchema { get; set; }
/// <summary>
/// Gets or sets the migrations history table's name.
/// Default is <see cref="DefaultMigrationsHistoryTableName"/>.
/// </summary>
public string MigrationsHistoryTableName { get; set; } = DefaultMigrationsHistoryTableName;
public Type DbContextType { get; set; }
}
}
using System;
using DotNetCore.CAP;
using DotNetCore.CAP.Kafka;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Contains extension methods to <see cref="CapBuilder"/> for adding kafka service.
/// </summary>
public static class CapBuilderExtensions
{
/// <summary>
/// Adds an Kafka implementation of CAP messages queue.
/// </summary>
/// <param name="builder">The <see cref="CapBuilder"/> instance this method extends</param>
/// <param name="setupAction">An action to configure the <see cref="KafkaOptions"/>.</param>
/// <returns>An <see cref="CapBuilder"/> for creating and configuring the CAP system.</returns>
public static CapBuilder AddKafka(this CapBuilder builder, Action<KafkaOptions> setupAction)
{
if (setupAction == null) throw new ArgumentNullException(nameof(setupAction));
builder.Services.Configure(setupAction);
builder.Services.AddSingleton<IConsumerClientFactory, KafkaConsumerClientFactory>();
builder.Services.AddTransient<IQueueExecutor, PublishQueueExecutor>();
return builder;
}
}
}
\ No newline at end of file
using System;
using DotNetCore.CAP.Kafka;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetCore.CAP
{
public class KafkaCapOptionsExtension : ICapOptionsExtension
{
private Action<KafkaOptions> _configure;
public KafkaCapOptionsExtension(Action<KafkaOptions> configure)
{
_configure = configure;
}
public void AddServices(IServiceCollection services)
{
services.Configure(_configure);
var kafkaOptions = new KafkaOptions();
_configure(kafkaOptions);
services.AddSingleton(kafkaOptions);
services.AddSingleton<IConsumerClientFactory, KafkaConsumerClientFactory>();
services.AddTransient<IQueueExecutor, PublishQueueExecutor>();
}
}
}
......@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
namespace DotNetCore.CAP.Kafka
namespace DotNetCore.CAP
{
/// <summary>
/// Provides programmatic configuration for the CAP kafka project.
......
using System;
using DotNetCore.CAP;
using DotNetCore.CAP.Kafka;
namespace Microsoft.Extensions.DependencyInjection
{
public static class CapOptionsExtensions
{
public static CapOptions UseKafka(this CapOptions options, string bootstrapServers)
{
return options.UseRabbitMQ(opt =>
{
opt.Servers = bootstrapServers;
});
}
public static CapOptions UseRabbitMQ(this CapOptions options, Action<KafkaOptions> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
options.RegisterExtension(new KafkaCapOptionsExtension(configure));
return options;
}
}
}
\ No newline at end of file
using System;
using DotNetCore.CAP;
using DotNetCore.CAP.RabbitMQ;
namespace Microsoft.Extensions.DependencyInjection
{
public static class CapBuilderExtensions
{
public static CapBuilder AddRabbitMQ(this CapBuilder builder, Action<RabbitMQOptions> setupOptions)
{
if (setupOptions == null) throw new ArgumentNullException(nameof(setupOptions));
builder.Services.Configure(setupOptions);
builder.Services.AddSingleton<IConsumerClientFactory, RabbitMQConsumerClientFactory>();
builder.Services.AddTransient<IQueueExecutor, PublishQueueExecutor>();
return builder;
}
}
}
\ No newline at end of file
using System;
using DotNetCore.CAP;
namespace Microsoft.Extensions.DependencyInjection
{
public static class CapOptionsExtensions
{
public static CapOptions UseRabbitMQ(this CapOptions options, string hostName)
{
return options.UseRabbitMQ(opt =>
{
opt.HostName = hostName;
});
}
public static CapOptions UseRabbitMQ(this CapOptions options, Action<RabbitMQOptions> configure)
{
if (configure == null) throw new ArgumentNullException(nameof(configure));
options.RegisterExtension(new RabbitMQCapOptionsExtension(configure));
return options;
}
}
}
\ No newline at end of file
namespace DotNetCore.CAP.RabbitMQ
namespace DotNetCore.CAP
{
public class RabbitMQOptions
{
......
using System;
using DotNetCore.CAP.RabbitMQ;
using Microsoft.Extensions.DependencyInjection;
namespace DotNetCore.CAP
{
public class RabbitMQCapOptionsExtension : ICapOptionsExtension
{
private Action<RabbitMQOptions> _configure;
public RabbitMQCapOptionsExtension(Action<RabbitMQOptions> configure)
{
_configure = configure;
}
public void AddServices(IServiceCollection services)
{
services.Configure(_configure);
var rabbitMQOptions = new RabbitMQOptions();
_configure(rabbitMQOptions);
services.AddSingleton(rabbitMQOptions);
services.AddSingleton<IConsumerClientFactory, RabbitMQConsumerClientFactory>();
services.AddTransient<IQueueExecutor, PublishQueueExecutor>();
}
}
}
namespace DotNetCore.CAP
using System;
namespace DotNetCore.CAP
{
/// <summary>
/// Represents all the options you can use to configure the system.
/// </summary>
public class CapOptions
{
internal ICapOptionsExtension Extension { get; private set; }
/// <summary>
/// Default value for polling delay timeout, in seconds.
/// </summary>
......@@ -30,5 +34,15 @@
/// Productor job polling delay time. Default is 8 sec.
/// </summary>
public int PollingDelay { get; set; } = 8;
/// <summary>
/// Registers an extension that will be executed when building services.
/// </summary>
/// <param name="extension"></param>
public void RegisterExtension(ICapOptionsExtension extension)
{
Extension = extension ?? throw new ArgumentNullException(nameof(extension));
}
}
}
\ No newline at end of file
......@@ -17,16 +17,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds and configures the CAP services for the consitence.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <returns>An <see cref="CapBuilder"/> for application services.</returns>
public static CapBuilder AddCap(this IServiceCollection services)
{
return services.AddCap(x => new CapOptions());
}
/// <summary>
/// Adds and configures the consistence services for the consitence.
/// </summary>
......@@ -37,6 +27,8 @@ namespace Microsoft.Extensions.DependencyInjection
this IServiceCollection services,
Action<CapOptions> setupAction)
{
if (setupAction == null) throw new ArgumentNullException(nameof(setupAction));
services.TryAddSingleton<CapMarkerService>();
services.Configure(setupAction);
......@@ -60,9 +52,12 @@ namespace Microsoft.Extensions.DependencyInjection
//Executors
services.AddSingleton<IQueueExecutorFactory, QueueExecutorFactory>();
services.AddSingleton<IQueueExecutor, SubscibeQueueExecutor>();
// services.TryAddScoped<ICapPublisher, DefaultCapPublisher>();
//Options
var options = new CapOptions();
setupAction(options);
options.Extension?.AddServices(services);
services.AddSingleton(options);
return new CapBuilder(services);
}
......
using Microsoft.Extensions.DependencyInjection;
namespace DotNetCore.CAP
{
public interface ICapOptionsExtension
{
void AddServices(IServiceCollection services);
}
}
using System;
using System.Threading.Tasks;
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Models;
using Microsoft.Extensions.Logging;
namespace DotNetCore.CAP
{
/// <summary>
/// Cap <see cref="ICapPublisher"/> default implement.
/// </summary>
public class DefaultCapPublisher : ICapPublisher
{
private readonly ILogger _logger;
public DefaultCapPublisher( ILogger<DefaultCapPublisher> logger)
{
_logger = logger;
}
public Task PublishAsync(string topic, string content)
{
if (topic == null) throw new ArgumentNullException(nameof(topic));
if (content == null) throw new ArgumentNullException(nameof(content));
return StoreMessage(topic, content);
}
public Task PublishAsync<T>(string topic, T contentObj)
{
if (topic == null) throw new ArgumentNullException(nameof(topic));
var content = Helper.ToJson(contentObj);
if (content == null)
throw new InvalidCastException(nameof(contentObj));
return StoreMessage(topic, content);
}
private async Task StoreMessage(string topic, string content)
{
var message = new CapSentMessage
{
KeyName = topic,
Content = content,
StatusName = StatusName.Enqueued
};
//await _store.StoreSentMessageAsync(message);
// WaitHandleEx.PulseEvent.Set();
// _logger.EnqueuingSentMessage(topic, content);
}
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ using DotNetCore.CAP.Processor;
using DotNetCore.CAP.Models;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
using System.Data;
namespace DotNetCore.CAP.Test
{
......@@ -34,17 +35,17 @@ namespace DotNetCore.CAP.Test
// Assert.NotNull(thingy);
//}
[Fact]
public void CanOverrideProducerService()
{
var services = new ServiceCollection();
services.AddCap().AddProducerService<MyProducerService>();
//[Fact]
//public void CanOverrideProducerService()
//{
// var services = new ServiceCollection();
// services.AddCap(x=> { });
var thingy = services.BuildServiceProvider()
.GetRequiredService<ICapPublisher>() as MyProducerService;
// var thingy = services.BuildServiceProvider()
// .GetRequiredService<ICapPublisher>() as MyProducerService;
Assert.NotNull(thingy);
}
// Assert.NotNull(thingy);
//}
private class MyProducerService : ICapPublisher
......@@ -58,6 +59,16 @@ namespace DotNetCore.CAP.Test
{
throw new NotImplementedException();
}
public Task PublishAsync(string topic, string content, IDbConnection dbConnection)
{
throw new NotImplementedException();
}
public Task PublishAsync(string topic, string content, IDbConnection dbConnection, IDbTransaction dbTransaction)
{
throw new NotImplementedException();
}
}
}
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ namespace DotNetCore.CAP.Test
services.AddScoped<IFooTest, CandidatesFooTest>();
services.AddScoped<IBarTest, CandidatesBarTest>();
services.AddLogging();
services.AddCap();
services.AddCap(x=> { });
_provider = services.BuildServiceProvider();
}
......
......@@ -14,12 +14,9 @@
<Compile Include="..\Shared\TestConsistencyMessage.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DotNetCore.CAP\DotNetCore.CAP.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.2" />
......@@ -28,6 +25,10 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DotNetCore.CAP\DotNetCore.CAP.csproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment