@@ -50,34 +50,98 @@ public static IServiceCollection AddMediator(this IServiceCollection services, g
5050 throw new global ::System . Exception ( errMsg ) ;
5151 }
5252
53+ // Build cache of existing registrations for efficient lookup
54+ var existingRegistrations = BuildRegistrationCache ( services ) ;
55+
5356 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Mediator ) , typeof ( global ::Mediator . Mediator ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
5457 services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . IMediator ) , sp => sp . GetRequiredService < global ::Mediator . Mediator > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
5558 services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . ISender ) , sp => sp . GetRequiredService < global ::Mediator . Mediator > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
5659 services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . IPublisher ) , sp => sp . GetRequiredService < global ::Mediator . Mediator > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
57-
60+
5861 // Register handlers and wrappers for notification messages
5962 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Internals . NotificationHandlerWrapper < global ::TestCode . Notification0 > ) , typeof ( global ::Mediator . Internals . NotificationHandlerWrapper < global ::TestCode . Notification0 > ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
6063 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Internals . NotificationHandlerWrapper < global ::TestCode . Notification1 > ) , typeof ( global ::Mediator . Internals . NotificationHandlerWrapper < global ::TestCode . Notification1 > ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
61-
64+
6265 // Register notification handlers
63- services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::TestCode . RequestHandler ) , typeof ( global ::TestCode . RequestHandler ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
64- services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification0 > ) , GetRequiredService < global ::TestCode . RequestHandler > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
65- services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification1 > ) , GetRequiredService < global ::TestCode . RequestHandler > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
66-
66+ if ( ! IsHandlerAlreadyRegistered ( existingRegistrations , typeof ( global ::TestCode . RequestHandler ) , typeof ( global ::TestCode . RequestHandler ) ) )
67+ services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::TestCode . RequestHandler ) , typeof ( global ::TestCode . RequestHandler ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
68+ if ( ! IsHandlerAlreadyRegistered ( existingRegistrations , typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification0 > ) , typeof ( global ::TestCode . RequestHandler ) ) )
69+ services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification0 > ) , GetRequiredService < global ::TestCode . RequestHandler > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
70+ if ( ! IsHandlerAlreadyRegistered ( existingRegistrations , typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification1 > ) , typeof ( global ::TestCode . RequestHandler ) ) )
71+ services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . INotificationHandler < global ::TestCode . Notification1 > ) , GetRequiredService < global ::TestCode . RequestHandler > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
72+
6773 // Register the notification publisher that was configured
6874 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . ForeachAwaitPublisher ) , typeof ( global ::Mediator . ForeachAwaitPublisher ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
6975 services . TryAdd ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . INotificationPublisher ) , sp => sp . GetRequiredService < global ::Mediator . ForeachAwaitPublisher > ( ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
70-
76+
7177 // Register internal components
7278 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Internals . IContainerProbe ) , typeof ( global ::Mediator . Internals . ContainerProbe0 ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
7379 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Internals . IContainerProbe ) , typeof ( global ::Mediator . Internals . ContainerProbe1 ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
7480 services . Add ( new global ::Microsoft . Extensions . DependencyInjection . ServiceDescriptor ( typeof ( global ::Mediator . Internals . ContainerMetadata ) , typeof ( global ::Mediator . Internals . ContainerMetadata ) , global ::Microsoft . Extensions . DependencyInjection . ServiceLifetime . Singleton ) ) ;
75-
81+
7682 return services ;
77-
83+
7884 [ global ::System . Runtime . CompilerServices . MethodImpl ( global ::System . Runtime . CompilerServices . MethodImplOptions . AggressiveInlining ) ]
7985 static global ::System . Func < global ::System . IServiceProvider , T > GetRequiredService < T > ( ) where T : notnull => sp => sp . GetRequiredService < T > ( ) ;
8086 }
87+
88+ /// <summary>
89+ /// Builds a cache of existing service registrations for efficient duplicate detection.
90+ /// Maps service types to their registered implementation types.
91+ /// </summary>
92+ /// <param name="services">The service collection to analyze</param>
93+ /// <returns>Dictionary mapping service types to sets of implementation types</returns>
94+ private static global ::System . Collections . Generic . Dictionary < global ::System . Type , global ::System . Collections . Generic . HashSet < global ::System . Type > >
95+ BuildRegistrationCache ( IServiceCollection services )
96+ {
97+ var cache = new global ::System . Collections . Generic . Dictionary < global ::System . Type , global ::System . Collections . Generic . HashSet < global ::System . Type > > ( ) ;
98+
99+ foreach ( var service in services )
100+ {
101+ if ( service . ServiceType == null ) continue ;
102+
103+ if ( ! cache . ContainsKey ( service . ServiceType ) )
104+ {
105+ cache [ service . ServiceType ] = new global ::System . Collections . Generic . HashSet < global ::System . Type > ( ) ;
106+ }
107+
108+ // Handle different ServiceDescriptor registration patterns
109+ if ( service . ImplementationType != null )
110+ {
111+ cache [ service . ServiceType ] . Add ( service . ImplementationType ) ;
112+ }
113+ else if ( service . ImplementationInstance != null )
114+ {
115+ cache [ service . ServiceType ] . Add ( service . ImplementationInstance . GetType ( ) ) ;
116+ }
117+ else if ( service . ImplementationFactory is { } implFac
118+ && implFac . Method . ReturnType . IsAssignableTo ( service . ServiceType )
119+ && implFac . Method . ReturnType . IsClass
120+ && implFac . Method . ReturnType != service . ServiceType )
121+ {
122+ // For factory registrations, mark service type as occupied
123+ cache [ service . ServiceType ] . Add ( implFac . Method . ReturnType ) ;
124+ }
125+ }
126+
127+ return cache ;
128+ }
129+
130+ /// <summary>
131+ /// Checks if a handler registration already exists in the service collection.
132+ /// </summary>
133+ /// <param name="existingRegistrations">Cache of existing registrations</param>
134+ /// <param name="serviceType">The service interface type</param>
135+ /// <param name="implementationType">The concrete implementation type</param>
136+ /// <returns>True if the handler is already registered</returns>
137+ private static bool IsHandlerAlreadyRegistered (
138+ global ::System . Collections . Generic . Dictionary < global ::System . Type , global ::System . Collections . Generic . HashSet < global ::System . Type > > existingRegistrations ,
139+ global ::System . Type serviceType ,
140+ global ::System . Type implementationType )
141+ {
142+ return existingRegistrations . ContainsKey ( serviceType ) &&
143+ existingRegistrations [ serviceType ] . Contains ( implementationType ) ;
144+ }
81145 }
82146}
83147
0 commit comments