| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- using Inversion;
- /**
- * Example demonstrating scope-local registrations.
- *
- * This shows how to register items directly on a scope,
- * which is useful for per-request context in web applications.
- */
- public class RequestContext : Object, IRequestContext {
- public string request_id { get; set; }
- public string path { get; set; }
-
- public RequestContext(string request_id, string path) {
- this.request_id = request_id;
- this.path = path;
- }
- }
- public interface IRequestContext : Object {
- public abstract string request_id { get; set; }
- public abstract string path { get; set; }
- }
- public class RequestLogger : Object {
- private RequestContext _context;
-
- public RequestLogger(RequestContext context) {
- this._context = context;
- }
-
- public void log(string message) {
- stdout.printf("[%s] %s\n", this._context.request_id, message);
- }
- }
- public class RequestHandler : Object {
- private RequestContext _context;
- private RequestLogger _logger;
-
- public RequestHandler(RequestContext context, RequestLogger logger) {
- this._context = context;
- this._logger = logger;
- }
-
- public void handle() {
- this._logger.log(@"Handling request for path: $(this._context.path)");
- this._logger.log("Request completed successfully");
- }
- }
- public class ApplicationService : Object {
- public void do_something() {
- stdout.printf("ApplicationService doing something...\n");
- }
- }
- void main() {
- // Create the main container with application-wide services
- var container = new Container();
-
- // Register application-wide singleton service
- container.register_singleton<ApplicationService>((scope) => {
- return new ApplicationService();
- });
-
- // Register handler as transient - it will receive scope-local dependencies
- container.register_transient<RequestHandler>((scope) => {
- var context = scope.resolve<RequestContext>();
- var logger = scope.resolve<RequestLogger>();
- return new RequestHandler(context, logger);
- });
-
- // Register logger as transient - it will receive scope-local context
- container.register_transient<RequestLogger>((scope) => {
- var context = scope.resolve<RequestContext>();
- return new RequestLogger(context);
- });
-
- stdout.printf("=== Simulating Web Request 1 ===\n\n");
-
- // Create a scope for the first request
- var scope1 = container.create_scope();
-
- // Register request-specific context in the scope using register_local_scoped
- var context1 = new RequestContext("req-001", "/api/users");
- scope1.register_local_scoped<RequestContext>((s) => context1);
-
- // Resolve and use the handler - it gets the request-specific context
- var handler1 = scope1.resolve<RequestHandler>();
- handler1.handle();
-
- // Also resolve the application service - comes from container
- var app_service1 = scope1.resolve<ApplicationService>();
- app_service1.do_something();
-
- stdout.printf("\n=== Simulating Web Request 2 ===\n\n");
-
- // Create a separate scope for the second request
- var scope2 = container.create_scope();
-
- // Register a different context for this request
- var context2 = new RequestContext("req-002", "/api/products");
- scope2.register_local_scoped<RequestContext>((s) => context2);
-
- // This handler gets the second request's context
- var handler2 = scope2.resolve<RequestHandler>();
- handler2.handle();
-
- stdout.printf("\n=== Demonstrating Fluent API with as_type ===\n\n");
-
- // Create a scope with an instance registered against an interface
- var scope3 = container.create_scope();
- var context3 = new RequestContext("req-003", "/api/fluent");
-
- // Use fluent API to register against multiple types
- scope3.register_local_scoped<RequestContext>((s) => context3)
- .as_type(typeof(IRequestContext)); // Also register as interface
-
- // Can now resolve by either the concrete type or interface
- var by_concrete = scope3.resolve<RequestContext>();
- var by_interface = scope3.resolve<IRequestContext>();
- stdout.printf("Resolved by concrete type: %s\n", by_concrete.request_id);
- stdout.printf("Resolved by interface: %s\n", by_interface.request_id);
- // Verify they're the same underlying object
- stdout.printf("Same instance: %s\n", ((Object)by_concrete) == ((Object)by_interface) ? "yes" : "no");
-
- stdout.printf("\n=== Demonstrating Scope Isolation ===\n\n");
-
- // Create a new scope - it does NOT inherit the other scope's local registrations
- var isolated_scope = container.create_scope();
-
- // This would throw because RequestContext is not registered in isolated scope
- try {
- var handler_isolated = isolated_scope.resolve<RequestHandler>();
- } catch (Error e) {
- stdout.printf("Expected error in isolated scope: %s\n", e.message);
- }
-
- stdout.printf("\n=== Demonstrating resolve_all with Both Sources ===\n\n");
-
- // Register an additional RequestContext in scope2 using transient
- scope2.register_local_transient<RequestContext>((s) => {
- return new RequestContext("req-002-secondary", "/api/products/secondary");
- });
-
- // resolve_all returns both scope-local and container registrations
- var all_contexts = scope2.resolve_all<RequestContext>();
- stdout.printf("All RequestContext instances:\n");
- foreach (var obj in all_contexts.to_immutable_buffer()) {
- if (obj != null) {
- var ctx = (RequestContext) obj;
- stdout.printf(" - %s: %s\n", ctx.request_id, ctx.path);
- }
- }
-
- stdout.printf("\n=== Scope-Local Scoped Factory Demo ===\n\n");
-
- var scope4 = container.create_scope();
-
- // Register a scoped factory - same instance returned within the scope
- scope4.register_local_scoped<RequestContext>((s) => {
- stdout.printf("Creating scoped RequestContext...\n");
- return new RequestContext("req-004", "/api/scoped");
- });
-
- // First resolution creates the instance
- var ctx4a = scope4.resolve<RequestContext>();
- stdout.printf("First resolution: %s\n", ctx4a.request_id);
-
- // Second resolution returns the cached instance
- var ctx4b = scope4.resolve<RequestContext>();
- stdout.printf("Second resolution: %s\n", ctx4b.request_id);
-
- // Verify they're the same instance
- stdout.printf("Same instance: %s\n", ctx4a == ctx4b ? "yes" : "no");
-
- stdout.printf("\nDone!\n");
- }
|