Header menu logo FCQRS

A Walkthrough: User Registration and Login

In this example, we will create a simple user registration and login system using FCQRS. The system will consist of a User aggregate that handles commands for registering and logging in users. The aggregate will emit events based on the commands it processes. We will also implement a simple actor that will manage the state of the User aggregate. You can find the full sample code in the sample folder of repo.

  1. Create a new F# project: dotnet new console -lang F# -n MyFCQRSApp
  2. Add the packages:
    dotnet add package FCQRS
    dotnet add package Hocon.Extensions.Configuration
    dotnet add package Microsoft.Extensions.Logging.Console
  3. Create a hocon configuration file: config.hocon
  4. Create an Environments module and implement IConfiguration: and ILoggerFactory:
open Microsoft.Extensions.Configuration
open Microsoft.Extensions.Logging

type AppEnv(config: IConfiguration, loggerFactory: ILoggerFactory) =
    interface ILoggerFactory with
        member _.AddProvider(provider: ILoggerProvider) : unit = 
            loggerFactory.AddProvider provider

        member _.CreateLogger(categoryName: string) : ILogger =
            loggerFactory.CreateLogger categoryName 

        member _.Dispose() : unit = loggerFactory.Dispose()

    interface IConfiguration with
        member _.Item
            with get (key: string) = config.[key]
            and set key v = config.[key] <- v

        member _.GetChildren() = config.GetChildren()
        member _.GetReloadToken() = config.GetReloadToken()
        member _.GetSection key = config.GetSection key

Above code acts as a composition root for the application environment. It wraps IConfiguration and ILoggerFactory, allowing you to manage configuration and logging in a clean and type-safe manner.

namespace System
namespace System.IO
namespace Microsoft
namespace Microsoft.Extensions
namespace Microsoft.Extensions.Configuration
namespace Hocon
namespace Hocon.Extensions
namespace Hocon.Extensions.Configuration
namespace Microsoft.Extensions.Logging
Multiple items
type AppEnv = interface IConfiguration interface ILoggerFactory new: config: IConfiguration * loggerFactory: ILoggerFactory -> AppEnv

--------------------
new: config: IConfiguration * loggerFactory: ILoggerFactory -> AppEnv
val config: IConfiguration
type IConfiguration = override GetChildren: unit -> IEnumerable<IConfigurationSection> override GetReloadToken: unit -> IChangeToken override GetSection: key: string -> IConfigurationSection member Item: string
<summary> Represents a set of key/value application configuration properties. </summary>
val loggerFactory: ILoggerFactory
type ILoggerFactory = inherit IDisposable override AddProvider: provider: ILoggerProvider -> unit override CreateLogger: categoryName: string -> ILogger
<summary> Represents a type used to configure the logging system and create instances of <see cref="T:Microsoft.Extensions.Logging.ILogger" /> from the registered <see cref="T:Microsoft.Extensions.Logging.ILoggerProvider" />s. </summary>
val provider: ILoggerProvider
type ILoggerProvider = inherit IDisposable override CreateLogger: categoryName: string -> ILogger
<summary> Represents a type that can create instances of <see cref="T:Microsoft.Extensions.Logging.ILogger" />. </summary>
type unit = Unit
ILoggerFactory.AddProvider(provider: ILoggerProvider) : unit
val categoryName: string
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
Multiple items
type ILogger = override BeginScope<'TState> : state: 'TState -> IDisposable override IsEnabled: logLevel: LogLevel -> bool override Log<'TState> : logLevel: LogLevel * eventId: EventId * state: 'TState * ``exception`` : exn * formatter: Func<'TState,exn,string> -> unit
<summary> Represents a type used to perform logging. </summary>
<remarks>Aggregates most logging patterns to a single method.</remarks>


--------------------
type ILogger<'TCategoryName> = inherit ILogger
<summary> A generic interface for logging where the category name is derived from the specified <typeparamref name="TCategoryName" /> type name. Generally used to enable activation of a named <see cref="T:Microsoft.Extensions.Logging.ILogger" /> from dependency injection. </summary>
<typeparam name="TCategoryName">The type whose name is used for the logger category name.</typeparam>
(extension) ILoggerFactory.CreateLogger<'T>() : ILogger<'T>
(extension) ILoggerFactory.CreateLogger(``type`` : System.Type) : ILogger
ILoggerFactory.CreateLogger(categoryName: string) : ILogger
System.IDisposable.Dispose() : unit
val key: string
val set: elements: 'T seq -> Set<'T> (requires comparison)
val v: string
IConfiguration.GetChildren() : System.Collections.Generic.IEnumerable<IConfigurationSection>
IConfiguration.GetReloadToken() : Extensions.Primitives.IChangeToken
IConfiguration.GetSection(key: string) : IConfigurationSection

Type something to start searching.