### CMake Installation Rules for Application Components Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/CMakeLists.txt Configures the installation process for the application. It sets up the installation prefix, defines directories for data and libraries, and installs the main executable, ICU data file, Flutter library, and any bundled plugin libraries. It also handles the re-copying of the assets directory and conditionally installs the AOT library. ```cmake set(BUILD_BUNDLE_DIR "$") set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) if(PLUGIN_BUNDLED_LIBRARIES) install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime) ``` -------------------------------- ### Complete MediatR Application Setup with Commands, Queries, and Middleware Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Illustrates a full application setup using Dart MediatR, including dependency injection for a repository, defining commands (`ICommand`) and queries (`IQuery`), registering handlers, and applying pipeline behaviors. The `setupMediator` function encapsulates the configuration. ```dart import 'package:mediatr/mediatr.dart'; // Repository class ItemsRepository { List items = ['item1', 'item2']; } // Commands class AddItemCommand extends ICommand { final String item; AddItemCommand(this.item); } class AddItemCommandHandler extends ICommandHandler { final ItemsRepository repo; AddItemCommandHandler(this.repo); @override Future call(AddItemCommand request) async { if (request.item.isEmpty) throw Exception('Item cannot be empty'); repo.items.add(request.item); } } // Queries class GetItemsQuery extends IQuery> {} class GetItemsQueryHandler extends IRequestHandler> { final ItemsRepository repo; GetItemsQueryHandler(this.repo); @override Future> call(GetItemsQuery request) async => repo.items; } // Logging middleware class LoggingBehavior extends IPipelineBehavior { @override Future process(IRequest request, RequestHandlerDelegate next) { print('New request: $request'); return next(request); } } // Setup function Mediator setupMediator() { final repo = ItemsRepository(); final pipeline = Pipeline()..addMiddleware(LoggingBehavior()); final mediator = Mediator(pipeline); mediator.registerHandler( () => AddItemCommandHandler(repo), ); mediator.registerHandler, GetItemsQueryHandler>( () => GetItemsQueryHandler(repo), ); return mediator; } // Application usage void main() async { final mediator = setupMediator(); // Add items via commands await mediator.send(AddItemCommand('new item')); // Query items final items = await mediator.send>(GetItemsQuery()); print(items); // Output: [item1, item2, new item] } ``` -------------------------------- ### CMake Installation Rules for Application Bundle Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Defines installation rules to create a relocatable application bundle. This includes cleaning the build directory, installing the executable, data files, libraries, and assets. ```cmake set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) endif() install(CODE " file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") " COMPONENT Runtime) set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime) install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endforeach(bundled_library) set(FLUTTER_ASSET_DIR_NAME "flutter_assets") install(CODE " file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") " COMPONENT Runtime) install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) ``` -------------------------------- ### Load Dart Entrypoint with Service Worker (JavaScript) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/web/index.html This JavaScript snippet is responsible for loading the main Dart entry point (main.dart.js) when the window loads. It configures the service worker with a version injected by the Flutter build process and then initializes and runs the Flutter engine and application. ```javascript var serviceWorkerVersion = null; window.addEventListener('load', function(ev) { // Download main.dart.js _flutter.loader.loadEntrypoint({ serviceWorker: { serviceWorkerVersion: serviceWorkerVersion, } }).then(function(engineInitializer) { return engineInitializer.initializeEngine(); }).then(function(appRunner) { return appRunner.runApp(); }); }); ``` -------------------------------- ### CMake Project Setup and Configuration Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Initializes the CMake project, sets the minimum version, project name, and executable name. It also defines the application ID and enables modern CMake policies. ```cmake cmake_minimum_required(VERSION 3.10) project(runner LANGUAGES CXX) set(BINARY_NAME "example") set(APPLICATION_ID "com.example.example") cmake_policy(SET CMP0063 NEW) set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") ``` -------------------------------- ### Implement Command Operations with ICommand and ICommandHandler in Dart Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Details how to use `ICommand` for operations that do not require a return value (void). It includes an example of a command handler (`ICommandHandler`) with built-in validation and error handling using custom exceptions. ```dart import 'package:mediatr/mediatr.dart'; // Define a command for adding an item class AddItemCommand extends ICommand { final String item; AddItemCommand(this.item); } // Custom exception for validation class EmptyItemException implements Exception { @override String toString() => 'Cannot add empty item'; } // Command handler with validation class AddItemCommandHandler extends ICommandHandler { final ItemsRepository repository; AddItemCommandHandler(this.repository); @override Future call(AddItemCommand request) async { if (request.item.isEmpty) { throw EmptyItemException(); } repository.items.add(request.item); } } // Usage final repo = ItemsRepository(); final mediator = Mediator(Pipeline()); mediator.registerHandler( () => AddItemCommandHandler(repo), ); // Execute command await mediator.send(AddItemCommand('new item')); // Handle validation errors try { await mediator.send(AddItemCommand('')); } on EmptyItemException catch (e) { print(e); // Output: Cannot add empty item } ``` -------------------------------- ### CMake Project Setup and Build Configuration Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/CMakeLists.txt Initializes the CMake project, sets the executable name, and defines build configuration types based on whether the generator is multi-config. It also sets default build types and configures settings for the 'Profile' build mode. ```cmake cmake_minimum_required(VERSION 3.14) project(example LANGUAGES CXX) set(BINARY_NAME "example") cmake_policy(SET CMP0063 NEW) get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(IS_MULTICONFIG) set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE) else() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() endif() set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") ``` -------------------------------- ### Configure Flutter Library and Headers (CMake) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/flutter/CMakeLists.txt This snippet configures the Flutter library and its associated headers. It sets the path to the Flutter library DLL and ICU data file, and defines a list of header files. These are then made available to the parent scope for installation and used to configure an INTERFACE library for Flutter. ```cmake set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") # Configuration provided via flutter tool. include(${EPHEMERAL_DIR}/generated_config.cmake) # TODO: Move the rest of this into files in ephemeral. See # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") # Published to parent scope for install step. set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS "flutter_export.h" "flutter_windows.h" "flutter_messenger.h" "flutter_plugin_registrar.h" "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") add_dependencies(flutter flutter_assemble) ``` -------------------------------- ### Install AOT Library Conditionally (CMake) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt This CMake code snippet conditionally installs the AOT library. It checks if the build type is not 'Debug' before proceeding with the installation. The library is installed to a specified destination directory within the 'Runtime' component. ```cmake if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) endif() ``` -------------------------------- ### CMake: Setting up Flutter library and headers Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/flutter/CMakeLists.txt This CMake code defines the Flutter library and its associated header files. It finds necessary system packages (PkgConfig, GTK, GLIB, GIO), sets paths to the Flutter library and ICU data file, and configures include directories and link libraries for the Flutter interface target. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) list(APPEND FLUTTER_LIBRARY_HEADERS "fl_basic_message_channel.h" "fl_binary_codec.h" "fl_binary_messenger.h" "fl_dart_project.h" "fl_engine.h" "fl_json_message_codec.h" "fl_json_method_codec.h" "fl_message_codec.h" "fl_method_call.h" "fl_method_channel.h" "fl_method_codec.h" "fl_method_response.h" "fl_plugin_registrar.h" "fl_plugin_registry.h" "fl_standard_message_codec.h" "fl_standard_method_codec.h" "fl_string_codec.h" "fl_value.h" "fl_view.h" "flutter_linux.h" ) list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") add_library(flutter INTERFACE) target_include_directories(flutter INTERFACE "${EPHEMERAL_DIR}" ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) add_dependencies(flutter flutter_assemble) ``` -------------------------------- ### Integrate Flutter Tool Backend (CMake) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/flutter/CMakeLists.txt This snippet sets up a custom command to integrate with the Flutter tool backend. It defines a phony output file to ensure the command runs every time and specifies the command to execute, including environment variables and the tool backend script. A custom target 'flutter_assemble' is created to depend on the outputs of this command. ```cmake # === Flutter tool backend === # _phony_ is a non-existent file to force this command to run every time, # since currently there's no way to get a full input/output list from the # flutter tool. set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ${PHONY_OUTPUT} COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" windows-x64 $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" ${FLUTTER_LIBRARY_HEADERS} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_APP} ) ``` -------------------------------- ### Configure C++ Wrapper Libraries (CMake) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/flutter/CMakeLists.txt This snippet defines static C++ wrapper libraries for Flutter plugins and applications. It lists core implementation sources, plugin-specific sources, and app-specific sources, then adds them to separate static libraries. These libraries are configured with standard settings, visibility, and linked against the main Flutter library. ```cmake # === Wrapper === list(APPEND CPP_WRAPPER_SOURCES_CORE "core_implementations.cc" "standard_codec.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_PLUGIN "plugin_registrar.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") list(APPEND CPP_WRAPPER_SOURCES_APP "flutter_engine.cc" "flutter_view_controller.cc" ) list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") # Wrapper sources needed for a plugin. add_library(flutter_wrapper_plugin STATIC ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ) apply_standard_settings(flutter_wrapper_plugin) set_target_properties(flutter_wrapper_plugin PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(flutter_wrapper_plugin PROPERTIES CXX_VISIBILITY_PRESET hidden) target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) target_include_directories(flutter_wrapper_plugin PUBLIC "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_plugin flutter_assemble) # Wrapper sources needed for the runner. add_library(flutter_wrapper_app STATIC ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_APP} ) apply_standard_settings(flutter_wrapper_app) target_link_libraries(flutter_wrapper_app PUBLIC flutter) target_include_directories(flutter_wrapper_app PUBLIC "${WRAPPER_ROOT}/include" ) add_dependencies(flutter_wrapper_app flutter_assemble) ``` -------------------------------- ### Create and Send a Request in Dart Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/README.md Demonstrates how to define a request, its handler, register the handler with the mediator, and send the request. The handler processes the request and returns a result. This is useful for implementing the command query responsibility segregation (CQRS) pattern. ```dart /// Create the request class AddRequest extends IRequest { final int i; AddRequest(this.i); } /// Create a request handler class AddRequestHandler extends IRequestHandler { @override Future call(AddRequest request) async { return request.i + 1; } } /// Register the handler to the mediator instance ( commonly stored as a singleton ) final mediator = Mediator(Pipeline()); mediator.registerHandler( () => AddRequestHandler(), ); /// Send the request through the mediator instance final added = await mediator.send( AddRequest(2), ); print(added); // prints 3 ``` -------------------------------- ### Publish and Subscribe to Events in Dart Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/README.md Illustrates how to publish domain events and subscribe to them using either functions or class instances. This enables decoupled communication between different parts of the application. ```dart /// create an event extending IDomainEvent class MyEvent extends IDomainEvent { @override String get name => 'MyEvent'; } mediator.publish(MyEvent()); /// subscribe on mediator instance var unsubscribeFunc = mediator.subscribeWithFunc((event){ print(event.name); }); /// call the func returned to unsubscribe unsubscribeFunc(); class MyEventHandler extends IEventHandler { @override Future call(MyEvent event) { print(event); } } var eventHandler = MyEventHandler(); mediator.subscribe(eventHandler); /// call unsubscribe with the same instance to remove the handler. mediator.unsubscribe(eventHandler); ``` -------------------------------- ### Initialize and Register Mediator Handler in Dart Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Demonstrates how to set up the `Mediator` class, optionally configure a pipeline, register a request handler, and send a request. This is the foundational step for using the library. ```dart import 'package:mediatr/mediatr.dart'; // Create a mediator with an optional pipeline final pipeline = Pipeline(); final mediator = Mediator(pipeline); // Register handlers for your requests mediator.registerHandler( () => MyRequestHandler(), ); // Send requests through the mediator final result = await mediator.send(MyRequest('data')); print(result); // Output from handler ``` -------------------------------- ### Implement Read Operations with IQuery in Dart Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Illustrates the use of `IQuery`, which extends `IRequest` and enforces a non-null return type. This is ideal for data retrieval operations where a result is always expected. It shows handler implementation with dependency injection. ```dart import 'package:mediatr/mediatr.dart'; // Define a query that returns a list of items class GetItemsQuery extends IQuery> {} // Handler implementation with repository dependency class GetItemsQueryHandler extends IRequestHandler> { final ItemsRepository repository; GetItemsQueryHandler(this.repository); @override Future> call(GetItemsQuery request) async { return repository.items; } } // Repository class class ItemsRepository { List items = ['item1', 'item2', 'item3']; } // Usage final repo = ItemsRepository(); final mediator = Mediator(Pipeline()); mediator.registerHandler, GetItemsQueryHandler>( () => GetItemsQueryHandler(repo), ); final items = await mediator.send>(GetItemsQuery()); print(items); // Output: [item1, item2, item3] ``` -------------------------------- ### CMake Dependency and Executable Definition Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Finds and checks for PkgConfig and GTK dependencies, adds a preprocessor definition for the application ID, and defines the main executable target with its source files and dependencies. ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") add_executable(${BINARY_NAME} "main.cc" "my_application.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" ) apply_standard_settings(${BINARY_NAME}) target_link_libraries(${BINARY_NAME} PRIVATE flutter) target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) add_dependencies(${BINARY_NAME} flutter_assemble) ``` -------------------------------- ### Publishing Domain Events with Handlers and Subscriptions Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Demonstrates how to define and publish domain events using `IDomainEvent`. Supports both class-based handlers (`IEventHandler`) and function-based subscriptions. Events are published using `mediator.publish()`. Unsubscribing is handled by `mediator.unsubscribe()` or the returned function. ```dart import 'package:mediatr/mediatr.dart'; // Define a domain event class UserCreatedEvent extends IDomainEvent { final String userId; final String email; UserCreatedEvent(this.userId, this.email); @override String get name => 'UserCreatedEvent'; } // Class-based event handler class UserCreatedEventHandler extends IEventHandler { @override Future call(UserCreatedEvent event) async { print('User created: ${event.userId} - ${event.email}'); // Send welcome email, update analytics, etc. } } // Usage final mediator = Mediator(Pipeline()); // Subscribe with a class handler final handler = UserCreatedEventHandler(); mediator.subscribe(handler); // Subscribe with a function final unsubscribe = mediator.subscribeWithFunc((event) { print('Function handler: ${event.name}'); }); // Publish the event (notifies all subscribers) await mediator.publish( UserCreatedEvent('user123', 'user@example.com'), ); // Output: // User created: user123 - user@example.com // Function handler: UserCreatedEvent // Unsubscribe when done mediator.unsubscribe(handler); unsubscribe(); // Unsubscribe function handler ``` -------------------------------- ### Implementing Pipeline Behaviors for Request Processing Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Shows how to create and use `IPipelineBehavior` to implement middleware for request processing. Behaviors like logging and validation wrap the request handler, executing before and/or after the main logic. Behaviors are added to a `Pipeline` instance. ```dart import 'package:mediatr/mediatr.dart'; // Logging middleware class LoggingBehavior extends IPipelineBehavior { @override Future process(IRequest request, RequestHandlerDelegate next) async { print('Processing request: ${request.runtimeType}'); final stopwatch = Stopwatch()..start(); final result = await next(request); stopwatch.stop(); print('Request completed in ${stopwatch.elapsedMilliseconds}ms'); return result; } } // Validation middleware class ValidationBehavior extends IPipelineBehavior { @override Future process(IRequest request, RequestHandlerDelegate next) async { // Add validation logic here print('Validating request: ${request.runtimeType}'); return next(request); } } // Usage - middleware executes in order added final pipeline = Pipeline() ..addMiddleware(LoggingBehavior()) ..addMiddleware(ValidationBehavior()); final mediator = Mediator(pipeline); // Register and send request - both middlewares will execute mediator.registerHandler( () => AddRequestHandler(), ); await mediator.send(AddRequest(5)); // Output: // Processing request: AddRequest // Validating request: AddRequest // Request completed in 1ms ``` -------------------------------- ### CMake: Custom command for Flutter tool backend Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/flutter/CMakeLists.txt This CMake code defines a custom command to execute the Flutter tool backend script. It's designed to run every time by using a phony output target. The command sets environment variables and passes platform and build type information to the script, generating the Flutter library and headers. ```cmake add_custom_command( OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/_phony_ COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" ${FLUTTER_LIBRARY_HEADERS} ) ``` -------------------------------- ### Configure Executable Target and Dependencies (CMake) Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/runner/CMakeLists.txt Defines the main executable target for the application, lists all necessary source files, and applies standard build settings. It also configures compiler definitions and links required libraries, ensuring proper integration with the Flutter build system. ```cmake cmake_minimum_required(VERSION 3.14) project(runner LANGUAGES CXX) # Define the application target. To change its name, change BINARY_NAME in the # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer # work. # # Any new source files that you add to the application should be added here. add_executable(${BINARY_NAME} WIN32 "flutter_window.cpp" "main.cpp" "utils.cpp" "win32_window.cpp" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" "Runner.rc" "runner.exe.manifest" ) # Apply the standard set of build settings. This can be removed for applications # that need different build settings. apply_standard_settings(${BINARY_NAME}) # Disable Windows macros that collide with C++ standard library functions. target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") # Add dependency libraries and include directories. Add any application-specific # dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") # Run the Flutter tool portions of the build. This must not be removed. add_dependencies(${BINARY_NAME} flutter_assemble) ``` -------------------------------- ### Add Middleware for All Requests in Dart Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/README.md Shows how to add a pipeline behavior (middleware) to the mediator. This middleware intercepts all requests before they are handled, allowing for cross-cutting concerns like logging or validation. ```dart class LoggingBehavior extends IPipelineBehavior { @override Future process(IRequest request, RequestHandlerDelegate next) { print(request); return next(request); } } final mediator = Mediator( Pipeline() ..addMiddleware( LoggingBehavior(), ), ); ``` -------------------------------- ### CMake: Custom list prepend function for older CMake versions Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/flutter/CMakeLists.txt This function mimics the behavior of `list(TRANSFORM ... PREPEND ...)` for CMake versions older than 3.10. It takes a list name and a prefix, then prepends the prefix to each element in the list, modifying the list in the parent scope. ```cmake function(list_prepend LIST_NAME PREFIX) set(NEW_LIST "") foreach(element ${${LIST_NAME}}) list(APPEND NEW_LIST "${PREFIX}${element}") endforeach(element) set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) endfunction() ``` -------------------------------- ### CMake Target Properties for Executable Output Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Sets the runtime output directory for the executable to a subdirectory within the build directory. This is done to ensure the executable launches correctly with its associated resources. ```cmake set_target_properties(${BINARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" ) ``` -------------------------------- ### CMake Build Type and Settings Application Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Sets the default build type to 'Debug' if not already defined and defines a function `APPLY_STANDARD_SETTINGS` to apply common compilation features, warnings, optimization levels, and definitions to targets. ```cmake if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release") endif() function(APPLY_STANDARD_SETTINGS TARGET) target_compile_features(${TARGET} PUBLIC cxx_std_14) target_compile_options(${TARGET} PRIVATE -Wall -Werror) target_compile_options(${TARGET} PRIVATE "<$>:-O3>") target_compile_definitions(${TARGET} PRIVATE "<$>:NDEBUG>") endfunction() ``` -------------------------------- ### Implement Request/Response Handling with IRequest and IRequestHandler in Dart Source: https://context7.com/georgopoulosgiannis/dart_mediatr/llms.txt Shows how to define a request (`IRequest`) and its corresponding handler (`IRequestHandler`). This pattern is used for operations that expect a return value. Each request type must have a unique handler registered. ```dart import 'package:mediatr/mediatr.dart'; // Define a request that returns an integer class AddRequest extends IRequest { final int value; AddRequest(this.value); } // Define the handler for this request class AddRequestHandler extends IRequestHandler { @override Future call(AddRequest request) async { return request.value + 1; } } // Usage final mediator = Mediator(Pipeline()); mediator.registerHandler( () => AddRequestHandler(), ); final result = await mediator.send(AddRequest(5)); print(result); // Output: 6 ``` -------------------------------- ### CMake Function for Standard Compilation Settings Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/CMakeLists.txt Defines a CMake function `APPLY_STANDARD_SETTINGS` that applies common compilation features and options to a target. This includes setting the C++ standard to C++17, enabling verbose warnings, treating warnings as errors, and disabling specific compiler warnings. ```cmake function(APPLY_STANDARD_SETTINGS TARGET) target_compile_features(${TARGET} PUBLIC cxx_std_17) target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") target_compile_options(${TARGET} PRIVATE /EHsc) target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") endfunction() ``` -------------------------------- ### CMake Flutter and Runner Subdirectory Inclusion Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/windows/CMakeLists.txt Includes the Flutter managed directory and the application's runner subdirectory. It also includes generated plugin build rules, which are essential for managing and integrating plugins into the application build process. ```cmake set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") add_subdirectory(${FLUTTER_MANAGED_DIR}) add_subdirectory("runner") include(flutter/generated_plugins.cmake) ``` -------------------------------- ### Cross-Building Configuration in CMake Source: https://github.com/georgopoulosgiannis/dart_mediatr/blob/main/example/linux/CMakeLists.txt Configures CMake for cross-building by setting the sysroot and adjusting find root path modes when a Flutter target sysroot is specified. This ensures correct library and include path resolution. ```cmake if(FLUTTER_TARGET_PLATFORM_SYSROOT) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) endif() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.