├── .editorconfig ├── .gitignore ├── AspNetDependencyInjection.Mvc ├── ApplicationDependencyInjectionBuilderExtensions.cs ├── AspNetDependencyInjection.Mvc.csproj ├── DependencyInjectionMvcControllerActivator.cs ├── DependencyInjectionMvcDependencyResolver.cs ├── Notes.txt └── Properties │ └── AssemblyInfo.cs ├── AspNetDependencyInjection.SignalR ├── ApplicationDependencyInjectionBuilderExtensions.cs ├── AspNetDependencyInjection.SignalR.csproj ├── Notes on Dependency Injection in SignalR.txt ├── Properties │ └── AssemblyInfo.cs ├── Scoped │ ├── ScopedAndiSignalRDependencyResolver.cs │ ├── ScopedAndiSignalRHubActivator.cs │ ├── ScopedAndiSignalRHubDispatcher - Scope diagnosis.cs │ └── ScopedAndiSignalRHubDispatcher.cs └── Unscoped │ ├── UnscopedAndiSignalRDependencyResolver.cs │ └── UnscopedAndiSignalRHubActivator.cs ├── AspNetDependencyInjection.Tests ├── AspNetDependencyInjection.Tests.csproj ├── ConfigurationTests.cs ├── Mvc │ └── MvcDependencyResolverTests.cs ├── Properties │ └── AssemblyInfo.cs ├── TestExtensions.cs └── WebApi │ ├── AspNetWebStack │ ├── BaseWebApiWebStackTests.cs │ ├── ControllerServicesTests.cs │ ├── DefaultHttpControllerActivatorTest.cs │ ├── DefaultServicesTests.cs │ └── ModelBinderAttributeTest.cs │ └── WebApiDependencyResolverTests.cs ├── AspNetDependencyInjection.Wcf ├── AspNetDependencyInjection.Wcf.csproj ├── Properties │ └── AssemblyInfo.cs └── WcfServiceDI │ ├── AndiInstanceProvider.cs │ └── AndiWebServiceHostFactory.cs ├── AspNetDependencyInjection.WebApi ├── ApplicationDependencyInjectionBuilderExtensions.cs ├── AspNetDependencyInjection.WebApi.csproj ├── DependencyInjectionWebApiDependencyResolver.cs └── Properties │ └── AssemblyInfo.cs ├── AspNetDependencyInjection.WithSamples.sln ├── AspNetDependencyInjection.sln ├── AspNetDependencyInjection ├── AspNetDependencyInjection.Configuration │ ├── AspNetDependencyInjectionConfigurationSection.cs │ ├── IgnoreNamespaceConfigurationElementCollection.cs │ ├── NamespaceConfigurationElement.cs │ └── NamespacePrefix.cs ├── AspNetDependencyInjection.Services │ ├── DependencyInjectionOverrides │ │ ├── DefaultDependencyInjectionOverrideService.cs │ │ ├── IDependencyInjectionOverrideService.cs │ │ └── ServiceCollectionExtensions.cs │ ├── HttpContextAccessor │ │ ├── HttpContextAccessor.cs │ │ ├── IHttpContextAccessor.cs │ │ └── ServiceCollectionExtensions.cs │ ├── ServiceFactory │ │ └── IServiceFactory.cs │ ├── ServiceProviderAccessor │ │ ├── DefaultServiceProviderAccessor.cs │ │ └── IServiceProviderAccessor.cs │ └── WebConfiguration │ │ ├── DefaultWebConfiguration.cs │ │ ├── IWebConfiguration.cs │ │ ├── IWebConfigurationExtensions.cs │ │ ├── PassthroughWebConfiguration.cs │ │ └── ServiceCollectionExtensions.cs ├── AspNetDependencyInjection.csproj ├── AspNetDependencyInjection │ ├── ActivatorServiceProvider.cs │ ├── ApplicationDependencyInjection.cs │ ├── ApplicationDependencyInjectionBuilder.cs │ ├── ApplicationDependencyInjectionConfiguration.cs │ ├── DependencyInjectionWebObjectActivator.cs │ ├── Extensions.cs │ ├── HttpContextScopeHttpModule.cs │ ├── HttpExtensions.cs │ ├── IDependencyInjectionClient.cs │ ├── IScopedHttpApplication.cs │ └── ObjectFactoryCache.cs └── Properties │ └── AssemblyInfo.cs ├── Common.props ├── GETTING_STARTED.md ├── LICENSE.txt ├── Normalize cobbled files.linq ├── README.md ├── SampleMvcWebApplication ├── App_Start │ ├── AppStartup.cs │ ├── FilterConfig.cs │ └── RouteConfig.cs ├── Controllers │ ├── HomeController.cs │ └── MessageHub.cs ├── Global.asax ├── Global.asax.cs ├── Properties │ └── AssemblyInfo.cs ├── SampleMvcWebApplication.csproj ├── SampleServices │ ├── ScopedService.cs │ ├── SingletonService.cs │ └── TransientService.cs ├── Views │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ └── _ViewStart.cshtml ├── Web.config ├── favicon.ico └── packages.config ├── SampleWcfApplication ├── IService1.cs ├── SampleServices │ ├── ScopedService.cs │ ├── SingletonService.cs │ └── TransientService.cs ├── SampleWcfApplication.csproj ├── Service1.svc └── Web.config ├── SampleWebApiService ├── App_Start │ └── AppStartup.cs ├── Controllers │ └── ValuesController.cs ├── Global.asax ├── Global.asax.cs ├── Properties │ └── AssemblyInfo.cs ├── SampleServices │ ├── ScopedService.cs │ ├── SingletonService.cs │ └── TransientService.cs ├── SampleWebApiService.csproj ├── Web.config └── packages.config ├── SampleWebApplication ├── App_Start │ ├── SampleApplicationStart.cs │ └── SampleApplicationStart.template.cs ├── Default.aspx ├── Default.aspx.cs ├── Default.aspx.designer.cs ├── Global.asax ├── Global.asax.cs ├── InjectedControl.ascx ├── InjectedControl.ascx.cs ├── InjectedControl.ascx.designer.cs ├── Properties │ └── AssemblyInfo.cs ├── SampleExcludedExternalControl.ascx ├── SampleExcludedExternalControl.ascx.cs ├── SampleExcludedExternalControl.ascx.designer.cs ├── SampleIncludedExternalControl.ascx ├── SampleIncludedExternalControl.ascx.cs ├── SampleIncludedExternalControl.ascx.designer.cs ├── SampleWebApplication.csproj ├── Service1.cs ├── Service2.cs ├── Service3.cs ├── Service4.cs ├── SingletonService.cs ├── Site.Master ├── Site.Master.designer.cs ├── Site.master.cs ├── Styles │ └── Site.css ├── Web.config └── packages.config ├── SampleWebApplicationVB ├── AppCode │ └── DevHttpClientHandler.vb ├── App_Start │ └── SampleApplicationStart.vb ├── Default.aspx ├── Default.aspx.designer.vb ├── Default.aspx.vb ├── Global.asax ├── Global.asax.vb ├── Properties │ └── AssemblyInfo.vb ├── SampleWebApplicationVB.vbproj ├── Site.Master ├── Site.master.vb ├── Styles │ └── Site.css ├── Web.config └── packages.config └── packages ├── Microsoft.Web.Infrastructure.1.0.0.0 ├── Microsoft.Web.Infrastructure.1.0.0.0.nupkg └── lib │ └── net40 │ └── Microsoft.Web.Infrastructure.dll └── repositories.config /AspNetDependencyInjection.Mvc/ApplicationDependencyInjectionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using AspNetDependencyInjection.Internal; 4 | 5 | namespace AspNetDependencyInjection 6 | { 7 | /// Extension methods for . 8 | public static class ApplicationDependencyInjectionBuilderExtensions 9 | { 10 | /// Call this method to set-up AspNetDependencyInjection for ASP.NET MVC. 11 | /// Cannot be null. 12 | /// Internally, this method adds to using . 13 | public static ApplicationDependencyInjectionBuilder AddMvcDependencyResolver( this ApplicationDependencyInjectionBuilder builder ) 14 | { 15 | if( builder == null ) throw new ArgumentNullException(nameof(builder)); 16 | 17 | return builder 18 | .AddClient( di => new DependencyInjectionMvcDependencyResolver( di ) ); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Mvc/AspNetDependencyInjection.Mvc.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {1B4BE5D4-F919-44E9-B570-151EEE5698DA} 7 | Unity.WebForms.StrongNameKey.pfx 8 | 9 | 10 | 11 | Jehoel.AspNetDependencyInjection.Mvc 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {7e9e872b-41be-4b55-9519-d2ff3f92eb4e} 23 | AspNetDependencyInjection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Mvc/DependencyInjectionMvcControllerActivator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web.Mvc; 8 | using System.Web.Routing; 9 | 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace AspNetDependencyInjection.Internal 13 | { 14 | /// Implementation of (which is used by , in-turn used by ) that uses . 15 | public class DependencyInjectionMvcControllerActivator : IControllerActivator 16 | { 17 | private readonly ApplicationDependencyInjection di; 18 | 19 | internal DependencyInjectionMvcControllerActivator( ApplicationDependencyInjection di ) 20 | { 21 | this.di = di ?? throw new ArgumentNullException(nameof(di)); 22 | } 23 | 24 | /// 25 | /// The default .DefaultControllerActivator first tries passing the 's concrete to .
26 | /// If that fails then it uses directly. It does not pass a to (e.g. with ).
27 | ///
28 | /// Whereas this implementation does.
29 | /// 30 | /// 31 | /// 32 | public IController Create( RequestContext requestContext, Type controllerType ) 33 | { 34 | if( requestContext is null ) throw new ArgumentNullException( nameof( requestContext ) ); 35 | if( controllerType is null ) throw new ArgumentNullException( nameof( controllerType ) ); 36 | 37 | Object instance; 38 | try 39 | { 40 | IServiceProvider sp = this.di.GetServiceProviderForHttpContext( requestContext.HttpContext ); 41 | instance = ActivatorUtilities.GetServiceOrCreateInstance( sp, controllerType ); 42 | } 43 | catch( Exception ex ) 44 | { 45 | const String msg = @"An error occurred when trying to create a controller of type ""{0}\""."; 46 | throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, msg, controllerType.FullName ), innerException: ex ); 47 | } 48 | 49 | if( instance is null ) 50 | { 51 | return null; 52 | } 53 | else if( instance is IController controller ) 54 | { 55 | return controller; 56 | } 57 | else 58 | { 59 | if( instance is IDisposable disposable ) 60 | { 61 | disposable.Dispose(); 62 | } 63 | 64 | const String msg = @"The requested type ""{0}"" is not an " + nameof(IController) + @" type."; 65 | throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, msg, controllerType.FullName ) ); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Mvc/Notes.txt: -------------------------------------------------------------------------------- 1 | * I'm unsure how MVC's IDependencyResolver is meant to work, so look at the canon test cases 2 | 3 | 4 | System.Web.Http.Dependencies.IDependencyScope 5 | GetService(Type) : return null if not found 6 | GetServices(Type) : return empty enumerable if not found 7 | 8 | * Explain these types: 9 | 10 | * IResolver 11 | * SingleServiceResolver 12 | * IControllerActivator 13 | * Default implementation: `DefaultControllerActivator` 14 | * Uses IDependencyResolver first, and falls-back to `Activator.CreateInstance(controllerType)` 15 | * IControllerFactory 16 | * Default implementation: `DefaultControllerFactory` 17 | * Uses IControllerActivator 18 | * ControllerBuilder 19 | * Uses `IControllerFactory` 20 | 21 | 22 | * Where is MVC's IDependencyResolver used? if we don't need to implement it... 23 | 24 | * BuildManagerCompiledView 25 | * Used to create DefaultViewPageActivator 26 | * BuildManagerViewEngine 27 | * Used to create DefaultViewPageActivator 28 | * Controller.Resolver 29 | * DefaultControllerFactory 30 | * Used to create DefaultControllerActivator 31 | * FilterProviderCollection 32 | * ModelBinderProviderCollection 33 | * ModelValidatorProviderCollection 34 | * MultiServiceResolver 35 | * where is this used? 36 | * SingleServiceResolver 37 | * where is this used? 38 | * ValueProviderFactoryCollection 39 | * ViewEngineCollection 40 | 41 | 42 | Known services that IDependencyResolver is used for: 43 | 44 | * IAsyncActionInvokerFactory (how doees this get resolved when it's an interface? - ah, it looks like all the call-sites have their own hardcoded fallback. 45 | * IActionInvokerFactory 46 | * ITempDataProviderFactory 47 | * SessionStateTempDataProvider 48 | * IActionInvoker 49 | * 50 | 51 | actually, maybe implementing IDependencyResolver is fine because the tests are only there for the *Default* implementation? 52 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Mvc/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | /* 6 | 7 | #if DEBUG 8 | 9 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests" )] 10 | 11 | #else 12 | 13 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests, PublicKey=" + 14 | "0024000004800000940000000602000000240000525341310004000001000100b5644bd32f0714" + 15 | "dce56bb49d687880774726f85935f8213aff7d200ef6b75d6103996e8e26410b54475eeaeae3dd" + 16 | "3b1f48900025d8e66a8beb6c0580416ca82a0ef3ee4794dc2c06aa0d5e23ca5e4efaef2c98cc66" + 17 | "3efb5f00ef1c20b962a432e61dbbd5f672841d39de5b5ee2d157341d5d28a43c9bb7493ec838c8" + 18 | "e94586a5" )] 19 | 20 | #endif 21 | 22 | */ 23 | [assembly: CLSCompliant(true)] 24 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/ApplicationDependencyInjectionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using AspNetDependencyInjection.Internal; 4 | 5 | namespace AspNetDependencyInjection 6 | { 7 | /// Extension methods for . 8 | public static class ApplicationDependencyInjectionBuilderExtensions 9 | { 10 | /// Use this method to add AspNetDependencyInjection support to SignalR. It uses a custom to manage scope lifetime of objects. You should prefer this method instead of unless you're certain you don't want scoped lifetimes in SignalR or if you experience issues with scoped lifetimes in SignalR. 11 | public static ApplicationDependencyInjectionBuilder AddScopedSignalRDependencyResolver( this ApplicationDependencyInjectionBuilder builder ) 12 | { 13 | if( builder == null ) throw new ArgumentNullException(nameof(builder)); 14 | 15 | return builder 16 | .AddClient( ( di, rootSP ) => new ScopedAndiSignalRDependencyResolver( di, rootSP ) ); 17 | } 18 | 19 | /// Use this method to add AspNetDependencyInjection support to SignalR. It only supports Singleton and Transient service lifetimes and does not support scoped lifetimes. It uses a custom that uses the root . This approach is much simpler than the approach used by so you may choose to use this method if you experience problems with scoped lifetimes. 20 | public static ApplicationDependencyInjectionBuilder AddUnscopedSignalRDependencyResolver( this ApplicationDependencyInjectionBuilder builder ) 21 | { 22 | if( builder == null ) throw new ArgumentNullException(nameof(builder)); 23 | 24 | // TODO: I want to add a way to add validation so there'll be an exception if both AddScoped and AddUnscoped are used at the same time. 25 | 26 | return builder 27 | .AddClient( ( di, rootSP ) => new UnscopedAndiSignalRDependencyResolver( di, rootSP ) ); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/AspNetDependencyInjection.SignalR.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {7CB50365-9558-4CD9-98D1-7E33BDAAE15B} 7 | Unity.WebForms.StrongNameKey.pfx 8 | 9 | 10 | 11 | Jehoel.AspNetDependencyInjection.SignalR 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {7e9e872b-41be-4b55-9519-d2ff3f92eb4e} 24 | AspNetDependencyInjection 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | /* 7 | 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle("AspNetDependencyInjection.SignalR")] 12 | [assembly: AssemblyDescription("")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("")] 15 | [assembly: AssemblyProduct("AspNetDependencyInjection.SignalR")] 16 | [assembly: AssemblyCopyright("Copyright © 2019")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | 20 | // Setting ComVisible to false makes the types in this assembly not visible 21 | // to COM components. If you need to access a type in this assembly from 22 | // COM, set the ComVisible attribute to true on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | [assembly: Guid("7cb50365-9558-4cd9-98d1-7e33bdaae15b")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | [assembly: AssemblyVersion("4.0.*")] 39 | //[assembly: AssemblyFileVersion("1.0.0.0")] 40 | 41 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests, PublicKey=" + 42 | "0024000004800000940000000602000000240000525341310004000001000100b5644bd32f0714" + 43 | "dce56bb49d687880774726f85935f8213aff7d200ef6b75d6103996e8e26410b54475eeaeae3dd" + 44 | "3b1f48900025d8e66a8beb6c0580416ca82a0ef3ee4794dc2c06aa0d5e23ca5e4efaef2c98cc66" + 45 | "3efb5f00ef1c20b962a432e61dbbd5f672841d39de5b5ee2d157341d5d28a43c9bb7493ec838c8" + 46 | "e94586a5" )] 47 | 48 | */ 49 | [assembly: CLSCompliant(true)] 50 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/Scoped/ScopedAndiSignalRHubActivator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.AspNet.SignalR.Hubs; 4 | 5 | namespace AspNetDependencyInjection.Internal 6 | { 7 | /// Factory for objects. Consumed by SignalR's . This implementation uses the current request or operation scope as controlled by . 8 | [CLSCompliant(false)] // `HubDescriptor` is not CLS-compliant. 9 | public class ScopedAndiSignalRHubActivator : IHubActivator 10 | { 11 | private readonly ScopedAndiSignalRDependencyResolver dr; 12 | 13 | /// Constructor. 14 | /// Required. Cannot be null. 15 | public ScopedAndiSignalRHubActivator( ScopedAndiSignalRDependencyResolver dr ) 16 | { 17 | this.dr = dr ?? throw new ArgumentNullException( nameof( dr ) ); 18 | } 19 | 20 | /// Creates a new instance of the object specified by . The current request or operation scope is used. If no scope is currently available then an exception is thrown. 21 | public IHub Create( HubDescriptor descriptor ) 22 | { 23 | if( descriptor is null ) throw new ArgumentNullException( nameof( descriptor ) ); 24 | 25 | // SignalR's IHubActivator always creates the requested object, even if it is not registered. 26 | // By default, SignalR (using its `DefaultHubActivator`) does require each Hub to be registered, but registering each Hub type is not required when using a DI engine that supports creating objects from non-registered types with constructor parameters. 27 | 28 | // This line below fails because MEDI will *not* create a non-registered type, even if the type has a constructor where all parameters are registered. 29 | // return (IHub)scope.ServiceProvider.GetRequiredService( serviceType: descriptor.HubType ); 30 | 31 | // ...so do this instead: 32 | 33 | Object instantiated = this.dr.CreateInstanceUsingScope( descriptor.HubType ); 34 | return (IHub)instantiated; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/Unscoped/UnscopedAndiSignalRDependencyResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.SignalR; 3 | using Microsoft.AspNet.SignalR.Hubs; 4 | 5 | namespace AspNetDependencyInjection.Internal 6 | { 7 | /// Implements SignalR's by using . 8 | [CLSCompliant(false)] // `HubDescriptor` is not CLS-compliant. 9 | public class UnscopedAndiSignalRDependencyResolver : DefaultDependencyResolver, IDependencyResolver, IDependencyInjectionClient 10 | { 11 | private readonly ApplicationDependencyInjection di; 12 | 13 | /// Constructor. Consuming applications should not create their own instances of . 14 | public UnscopedAndiSignalRDependencyResolver( ApplicationDependencyInjection di, IServiceProvider rootServiceProvider ) 15 | : base() 16 | { 17 | this.di = di ?? throw new ArgumentNullException( nameof(di) ); 18 | this.RootServiceProvider = rootServiceProvider ?? throw new ArgumentNullException( nameof(rootServiceProvider) ); 19 | 20 | // 21 | 22 | this.HubActivator = new UnscopedAndiSignalRHubActivator( this ); 23 | 24 | this.Register( typeof(IHubActivator), () => this.HubActivator ); 25 | 26 | GlobalHost.DependencyResolver = this; 27 | } 28 | 29 | internal ObjectFactoryCache ObjectFactoryCache => this.di.ObjectFactoryCache; 30 | 31 | internal IServiceProvider RootServiceProvider { get; } 32 | 33 | /// Gets the singleton instance that SignalR will use to construct each object instance. 34 | public IHubActivator HubActivator { get; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.SignalR/Unscoped/UnscopedAndiSignalRHubActivator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.SignalR.Hubs; 3 | 4 | namespace AspNetDependencyInjection.Internal 5 | { 6 | /// Factory for objects. Consumed by SignalR's . This implementation does not use any scopes for limiting the lifetime of services. 7 | [CLSCompliant(false)] 8 | public class UnscopedAndiSignalRHubActivator : IHubActivator 9 | { 10 | private readonly UnscopedAndiSignalRDependencyResolver dr; 11 | 12 | /// Constructor. 13 | /// Required. Cannot be null. 14 | public UnscopedAndiSignalRHubActivator( UnscopedAndiSignalRDependencyResolver dr ) 15 | { 16 | this.dr = dr ?? throw new ArgumentNullException( nameof( dr ) ); 17 | } 18 | 19 | /// Creates a new instance of the object specified by . 20 | public IHub Create( HubDescriptor descriptor ) 21 | { 22 | if( descriptor is null ) throw new ArgumentNullException( nameof( descriptor ) ); 23 | 24 | Object instantiated = this.dr.ObjectFactoryCache.GetRequiredService( this.dr.RootServiceProvider, descriptor.HubType ); 25 | return (IHub)instantiated; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | /* 7 | 8 | [assembly: AssemblyTitle( "AspNetDependencyInjection.Tests" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "AspNetDependencyInjection.Tests" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2019 - Dai Rees (@Jehoel on GitHub)" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | [assembly: ComVisible( false )] 18 | 19 | [assembly: Guid( "7ff0b492-def1-4005-a899-0e82910481c4" )] 20 | 21 | // [assembly: AssemblyVersion("1.0.*")] 22 | [assembly: AssemblyVersion( "1.0.0.0" )] 23 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 24 | 25 | */ 26 | //[assembly: CLSCompliant(true)] 27 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/TestExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using AspNetDependencyInjection.Internal; 8 | 9 | namespace AspNetDependencyInjection.Tests 10 | { 11 | public static class TestExtensions 12 | { 13 | public static IReadOnlyList GetClients( this ApplicationDependencyInjection di ) 14 | { 15 | IHasDependencyInjectionClients asInterface = (IHasDependencyInjectionClients)di; 16 | 17 | return asInterface.Clients; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/WebApi/AspNetWebStack/BaseWebApiWebStackTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web.Http; 6 | using System.Web.Http.Controllers; 7 | using System.Web.Http.Dependencies; 8 | 9 | using AspNetDependencyInjection.Internal; 10 | 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace AspNetDependencyInjection.Tests.WebApi 14 | { 15 | public abstract class BaseWebApiWebStackTests 16 | { 17 | protected class SimpleController : ApiController 18 | { 19 | } 20 | 21 | protected class TestActionValueBinder : IActionValueBinder 22 | { 23 | private static Int32 _idSeed = 0; 24 | 25 | public TestActionValueBinder() 26 | { 27 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 28 | } 29 | 30 | public HttpActionBinding GetBinding( HttpActionDescriptor actionDescriptor ) 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | 35 | public Int32 InstanceId { get; } 36 | } 37 | 38 | protected class DependencyResolverWrapper : IDependencyResolver 39 | { 40 | private readonly IDependencyResolver inner; 41 | private readonly Boolean allowBeginScope; 42 | 43 | public DependencyResolverWrapper( IDependencyResolver inner, Boolean allowBeginScope ) 44 | { 45 | this.inner = inner; 46 | this.allowBeginScope = allowBeginScope; 47 | } 48 | 49 | public IDependencyScope BeginScope() 50 | { 51 | if( this.allowBeginScope ) 52 | { 53 | return this.inner.BeginScope(); 54 | } 55 | else 56 | { 57 | // This is the custom logic set in the original `Create_ThrowsForNullDependencyScope`. 58 | return null; 59 | } 60 | } 61 | 62 | public List GetServiceCalls { get; } = new List(); 63 | public List GetServicesCalls { get; } = new List(); 64 | 65 | public Object GetService( Type serviceType ) 66 | { 67 | this.GetServiceCalls.Add( serviceType ); 68 | return this.inner.GetService( serviceType ); 69 | } 70 | 71 | public IEnumerable GetServices( Type serviceType ) 72 | { 73 | this.GetServicesCalls.Add( serviceType ); 74 | return this.inner.GetServices( serviceType ); 75 | } 76 | 77 | public void Dispose() 78 | { 79 | this.inner.Dispose(); 80 | } 81 | } 82 | 83 | protected void WrapTest( Action configure, Action testImpl ) 84 | { 85 | this.WrapTest( configure, testImpl: ( resolver, arg ) => testImpl( resolver ), arg: default ); 86 | } 87 | 88 | protected void WrapTest( Action configure, Action testImpl, T arg ) 89 | { 90 | HttpConfiguration nonSystemWebConfiguration = new HttpConfiguration(); 91 | 92 | ApplicationDependencyInjection di = new ApplicationDependencyInjectionBuilder() 93 | .ConfigureServices( configure ) 94 | .AddWebApiDependencyResolver( nonSystemWebConfiguration ) 95 | .Build(); 96 | 97 | using( di ) 98 | { 99 | DependencyInjectionWebApiDependencyResolver webApiResolverInstance = di.GetClients() 100 | .OfType() 101 | .Single(); 102 | 103 | IDependencyResolver webApiResolver = webApiResolverInstance; 104 | 105 | testImpl( webApiResolver, arg ); 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/WebApi/AspNetWebStack/ControllerServicesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Web.Http; 4 | using System.Web.Http.Controllers; 5 | using System.Web.Http.Dependencies; 6 | 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.DependencyInjection.Extensions; 9 | 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | 12 | using Shouldly; 13 | 14 | namespace AspNetDependencyInjection.Tests.WebApi 15 | { 16 | /// Ripped from AspNetWebStack's test suite. 17 | [TestClass] 18 | public class ControllerServicesTests : BaseWebApiWebStackTests 19 | { 20 | [TestMethod] 21 | public void Controller_Overrides_DependencyInjection() 22 | { 23 | TestActionValueBinder newDIService = new TestActionValueBinder(); 24 | 25 | this.WrapTest( 26 | services => 27 | { 28 | _ = services.AddSingleton( implementationInstance: newDIService ); 29 | // _ = services.AddScoped(); 30 | }, 31 | this.Controller_Overrides_DependencyInjection_Impl, 32 | newDIService 33 | ); 34 | } 35 | 36 | private void Controller_Overrides_DependencyInjection_Impl( IDependencyResolver resolver, TestActionValueBinder newDIService ) 37 | { 38 | if( resolver is null ) throw new ArgumentNullException( nameof( resolver ) ); 39 | 40 | // Calling `.BeginScope()` here is to simulate what happens inside `DefaultHttpControllerActivator.GetInstanceOrActivator` 41 | using( IDependencyScope requestScope = resolver.BeginScope() ) 42 | { 43 | _ = requestScope.ShouldNotBeNull(); 44 | 45 | // Setting on Controller config overrides the DI container. 46 | HttpConfiguration config = new HttpConfiguration(); 47 | 48 | // IActionValueBinder newDIService = new TestActionValueBinder(); 49 | 50 | config.DependencyResolver = resolver; 51 | 52 | ControllerServices cs = new ControllerServices(config.Services); 53 | 54 | IActionValueBinder newLocalService = new TestActionValueBinder(); 55 | cs.Replace(typeof(IActionValueBinder), newLocalService); 56 | 57 | // Act 58 | IActionValueBinder localVal = (IActionValueBinder)cs.GetService(typeof(IActionValueBinder)); 59 | IActionValueBinder globalVal = (IActionValueBinder)config.Services.GetService(typeof(IActionValueBinder)); 60 | 61 | _ = localVal .ShouldNotBeNull().ShouldBeOfType(); 62 | _ = globalVal.ShouldNotBeNull().ShouldBeOfType(); 63 | 64 | // Assert 65 | // Local controller didn't override, should get same value as global case. 66 | Object.ReferenceEquals( newDIService, globalVal ).ShouldBeTrue(); // asking the config will give back the DI service 67 | Object.ReferenceEquals( newLocalService, localVal ).ShouldBeTrue(); // but asking locally will get back the local service. 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/WebApi/AspNetWebStack/DefaultHttpControllerActivatorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Web.Http; 6 | using System.Web.Http.Controllers; 7 | using System.Web.Http.Dependencies; 8 | using System.Web.Http.Dispatcher; 9 | 10 | using AspNetDependencyInjection.Internal; 11 | 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.DependencyInjection.Extensions; 14 | 15 | using Microsoft.VisualStudio.TestTools.UnitTesting; 16 | 17 | using Shouldly; 18 | 19 | namespace AspNetDependencyInjection.Tests.WebApi 20 | { 21 | /// Ripped from AspNetWebStack's test suite. 22 | [TestClass] 23 | public class DefaultHttpControllerActivatorTest : BaseWebApiWebStackTests 24 | { 25 | /// 26 | /// System.Web.Http.Dispatcher.DefaultHttpControllerActivatorTest
27 | /// AspNetWebStack\test\System.Web.Http.Test\Dispatcher\DefaultHttpControllerActivatorTest.cs 28 | ///
29 | [TestMethod] 30 | public void Create_ThrowsForNullDependencyScope() 31 | { 32 | this.WrapTest( services => services.AddTransient(), this.Create_ThrowsForNullDependencyScope_Impl ); 33 | } 34 | 35 | private void Create_ThrowsForNullDependencyScope_Impl( IDependencyResolver resolverOrig ) 36 | { 37 | IDependencyResolver resolver2 = new DependencyResolverWrapper( inner: resolverOrig, allowBeginScope: false ); 38 | 39 | // Arrange 40 | HttpConfiguration config = new HttpConfiguration(); 41 | config.DependencyResolver = resolver2; 42 | 43 | HttpRequestMessage request = new HttpRequestMessage(); 44 | request.SetConfiguration(config); 45 | 46 | HttpControllerDescriptor descriptorSimpleController = new HttpControllerDescriptor(config, "Simple", typeof(SimpleController)); 47 | 48 | DefaultHttpControllerActivator activator = new DefaultHttpControllerActivator(); 49 | 50 | // Act & Assert 51 | try 52 | { 53 | IHttpController controller = activator.Create( request, descriptorSimpleController, typeof(SimpleController) ); 54 | 55 | true.ShouldBeFalse( "Method did not throw an exception." ); 56 | } 57 | catch( InvalidOperationException ioEx ) 58 | { 59 | ioEx.Message.ShouldBe( "An error occurred when trying to create a controller of type 'SimpleController'. Make sure that the controller has a parameterless public constructor." ); 60 | 61 | // 'BeginScopeNull_DependencyResolver' 62 | // 'ObjectProxy(_\\d+)?' 63 | 64 | ioEx.InnerException.Message.ShouldBe( 65 | "A dependency resolver of type '" + nameof(DependencyResolverWrapper) + "' returned an invalid value of null from its " + 66 | "BeginScope method. If the container does not have a concept of scope, consider returning a scope " + 67 | "that resolves in the root of the container instead." 68 | ); 69 | 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/WebApi/AspNetWebStack/ModelBinderAttributeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | using System.Web.Http.Dependencies; 6 | using System.Web.Http.ModelBinding; 7 | 8 | using AspNetDependencyInjection.Internal; 9 | 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | 12 | using Shouldly; 13 | 14 | namespace AspNetDependencyInjection.Tests.WebApi 15 | { 16 | /// Ripped from AspNetWebStack's test suite. 17 | [TestClass] 18 | public class ModelBinderAttributeTest : BaseWebApiWebStackTests 19 | { 20 | 21 | 22 | /// 23 | /// SSystem.Web.Http.ModelBinding.ModelBinderAttributeTest
24 | /// AspNetWebStack\test\System.Web.Http.Test\ModelBinding\ModelBinderAttributeTest.cs 25 | ///
26 | [TestMethod] 27 | public void BinderType_From_DependencyResolver() 28 | { 29 | this.WrapTest( services => services.AddScoped(), this.Controller_Overrides_DependencyInjection_Impl ); 30 | } 31 | 32 | private void BinderType_From_DependencyResolver_Impl( IDependencyResolver resolver ) 33 | { 34 | // To test dependency resolver, the registered type and actual type should be different. 35 | HttpConfiguration config = new HttpConfiguration(); 36 | var mockDependencyResolver = new Mock(); 37 | mockDependencyResolver.Setup(r => r.GetService(typeof(CustomModelBinderProvider))).Returns(new SecondCustomModelBinderProvider()); 38 | config.DependencyResolver = mockDependencyResolver.Object; 39 | 40 | ModelBinderAttribute attr = new ModelBinderAttribute(typeof(CustomModelBinderProvider)); 41 | 42 | ModelBinderProvider provider = attr.GetModelBinderProvider(config); 43 | Assert.IsType(provider); 44 | } 45 | 46 | /// 47 | /// System.Web.Http.ModelBinding.ModelBinderAttributeTest
48 | /// AspNetWebStack\test\System.Web.Http.Test\ModelBinding\ModelBinderAttributeTest.cs 49 | ///
50 | [TestMethod] 51 | public void BinderType_From_DependencyResolver_ReleasedWhenConfigIsDisposed() 52 | { 53 | // Arrange 54 | HttpConfiguration config = new HttpConfiguration(); 55 | var mockDependencyResolver = new Mock(); 56 | SecondCustomModelBinderProvider provider = new SecondCustomModelBinderProvider(); 57 | mockDependencyResolver.Setup(r => r.GetService(typeof(CustomModelBinderProvider))).Returns(provider); 58 | config.DependencyResolver = mockDependencyResolver.Object; 59 | 60 | ModelBinderAttribute attr = new ModelBinderAttribute(typeof(CustomModelBinderProvider)); 61 | attr.GetModelBinderProvider(config); 62 | 63 | // Act 64 | config.Dispose(); 65 | 66 | // Assert 67 | mockDependencyResolver.Verify(dr => dr.Dispose(), Times.Once()); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Tests/WebApi/WebApiDependencyResolverTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | using System.Web.Http.Dependencies; 6 | 7 | using AspNetDependencyInjection.Internal; 8 | 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | using Shouldly; 12 | 13 | namespace AspNetDependencyInjection.Tests.WebApi 14 | { 15 | [TestClass] 16 | public class WebApiDependencyResolverTests 17 | { 18 | [TestMethod] 19 | public void AddWebApiDependencyResolver_should_add_single_DependencyInjectionWebApiDependencyResolver() 20 | { 21 | HttpConfiguration unitTestWebApiConfiguration = new HttpConfiguration(); 22 | 23 | ApplicationDependencyInjection di = new ApplicationDependencyInjectionBuilder() 24 | .AddWebApiDependencyResolver( unitTestWebApiConfiguration ) 25 | .Build(); 26 | 27 | using( di ) 28 | { 29 | Int32 count = di.GetClients() 30 | .OfType() 31 | .Count(); 32 | 33 | count.ShouldBe( expected: 1 ); 34 | } 35 | } 36 | 37 | [TestMethod] 38 | public void WebApi_DependencyResolver_GetService_should_return_null_when_unresolved() 39 | { 40 | HttpConfiguration unitTestWebApiConfiguration = new HttpConfiguration(); 41 | 42 | ApplicationDependencyInjection di = new ApplicationDependencyInjectionBuilder() 43 | .ConfigureServices( services => { } ) 44 | .AddWebApiDependencyResolver( unitTestWebApiConfiguration ) 45 | .Build(); 46 | 47 | using( di ) 48 | { 49 | DependencyInjectionWebApiDependencyResolver webApiResolverInstance = di.GetClients() 50 | .OfType() 51 | .Single(); 52 | 53 | // 54 | 55 | IDependencyResolver webApiResolver = webApiResolverInstance; 56 | 57 | // 58 | 59 | { 60 | Object implementation = webApiResolver.GetService( typeof(INonRegisteredService) ); 61 | implementation.ShouldBeNull(); 62 | } 63 | 64 | // And call it again for good measure: 65 | { 66 | Object implementation = webApiResolver.GetService( typeof(INonRegisteredService) ); 67 | implementation.ShouldBeNull(); 68 | } 69 | } 70 | } 71 | 72 | [TestMethod] 73 | public void WebApi_DependencyResolver_GetServices_should_return_empty_enumerable_when_unresolved() 74 | { 75 | HttpConfiguration unitTestWebApiConfiguration = new HttpConfiguration(); 76 | 77 | ApplicationDependencyInjection di = new ApplicationDependencyInjectionBuilder() 78 | .ConfigureServices( services => { } ) 79 | .AddWebApiDependencyResolver( unitTestWebApiConfiguration ) 80 | .Build(); 81 | 82 | using( di ) 83 | { 84 | DependencyInjectionWebApiDependencyResolver webApiResolverInstance = di.GetClients() 85 | .OfType() 86 | .Single(); 87 | 88 | // 89 | 90 | IDependencyResolver webApiResolver = webApiResolverInstance; 91 | 92 | // 93 | 94 | IEnumerable services = webApiResolver.GetServices( typeof(INonRegisteredService) ); 95 | _ = services.ShouldNotBeNull(); 96 | services.Count().ShouldBe( expected: 0 ); 97 | 98 | // Check twice, in case of IEnumerable implementation shenanigans: 99 | services.Count().ShouldBe( expected: 0 ); 100 | } 101 | } 102 | } 103 | 104 | internal interface INonRegisteredService 105 | { 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Wcf/AspNetDependencyInjection.Wcf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {F1B12590-1707-4CB3-BA70-F6AE906E475D} 7 | Unity.WebForms.StrongNameKey.pfx 8 | 9 | 10 | 11 | Jehoel.AspNetDependencyInjection.Wcf 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {7e9e872b-41be-4b55-9519-d2ff3f92eb4e} 30 | AspNetDependencyInjection 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Wcf/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | /* 7 | 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle( "AspNetDependencyInjection.Wcf" )] 12 | [assembly: AssemblyDescription( "" )] 13 | [assembly: AssemblyConfiguration( "" )] 14 | [assembly: AssemblyCompany( "" )] 15 | [assembly: AssemblyProduct( "AspNetDependencyInjection.Wcf" )] 16 | [assembly: AssemblyCopyright( "Copyright © 2019" )] 17 | [assembly: AssemblyTrademark( "" )] 18 | [assembly: AssemblyCulture( "" )] 19 | 20 | // Setting ComVisible to false makes the types in this assembly not visible 21 | // to COM components. If you need to access a type in this assembly from 22 | // COM, set the ComVisible attribute to true on that type. 23 | [assembly: ComVisible( false )] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | [assembly: Guid( "f1b12590-1707-4cb3-ba70-f6ae906e475d" )] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Revision and Build Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | [assembly: AssemblyVersion( "1.0.0.0" )] 39 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 40 | 41 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests, PublicKey=" + 42 | "0024000004800000940000000602000000240000525341310004000001000100b5644bd32f0714" + 43 | "dce56bb49d687880774726f85935f8213aff7d200ef6b75d6103996e8e26410b54475eeaeae3dd" + 44 | "3b1f48900025d8e66a8beb6c0580416ca82a0ef3ee4794dc2c06aa0d5e23ca5e4efaef2c98cc66" + 45 | "3efb5f00ef1c20b962a432e61dbbd5f672841d39de5b5ee2d157341d5d28a43c9bb7493ec838c8" + 46 | "e94586a5" )] 47 | 48 | */ 49 | 50 | [assembly: CLSCompliant( isCompliant: true )] 51 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Wcf/WcfServiceDI/AndiInstanceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ServiceModel; 3 | using System.ServiceModel.Channels; 4 | using System.ServiceModel.Description; 5 | using System.ServiceModel.Dispatcher; 6 | 7 | namespace AspNetDependencyInjection.Wcf 8 | { 9 | /// Implements and . 10 | public sealed class AndiInstanceProvider : IInstanceProvider, IContractBehavior 11 | { 12 | private readonly IServiceProvider serviceProvider; 13 | 14 | /// Constructor. This is called by when extending 's . 15 | public AndiInstanceProvider( IServiceProvider serviceProvider ) 16 | { 17 | this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); 18 | } 19 | 20 | #region IContractBehavior 21 | 22 | void IContractBehavior.AddBindingParameters( ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters ) 23 | { 24 | } 25 | 26 | void IContractBehavior.ApplyClientBehavior( ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime ) 27 | { 28 | } 29 | 30 | void IContractBehavior.ApplyDispatchBehavior( ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime ) 31 | { 32 | dispatchRuntime.InstanceProvider = this; 33 | } 34 | 35 | void IContractBehavior.Validate( ContractDescription contractDescription, ServiceEndpoint endpoint ) 36 | { 37 | } 38 | 39 | #endregion 40 | 41 | #region IInstanceProvider 42 | 43 | Object IInstanceProvider.GetInstance( InstanceContext instanceContext ) 44 | { 45 | Type serviceType = instanceContext.Host.Description.ServiceType; // TODO: Is this an injected-service type or a WCF service type? 46 | return this.serviceProvider.GetService( serviceType ); 47 | } 48 | 49 | Object IInstanceProvider.GetInstance( InstanceContext instanceContext, Message message ) 50 | { 51 | IInstanceProvider selfAsIInstanceProvider = this; 52 | return selfAsIInstanceProvider.GetInstance( instanceContext ); 53 | } 54 | 55 | void IInstanceProvider.ReleaseInstance( InstanceContext instanceContext, Object instance ) 56 | { 57 | if( instance is IDisposable disposable ) 58 | { 59 | disposable.Dispose(); 60 | } 61 | } 62 | 63 | #endregion 64 | 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.Wcf/WcfServiceDI/AndiWebServiceHostFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.ServiceModel; 4 | using System.ServiceModel.Activation; 5 | using System.ServiceModel.Description; 6 | using System.ServiceModel.Web; 7 | using System.Web; 8 | 9 | namespace AspNetDependencyInjection.Wcf 10 | { 11 | // All services are singletons or non-disposable transients (via factories) btw - no support for scoped services here. 12 | 13 | /// Subclass of which creates instances. 14 | public class AndiWebServiceHostFactory : WebServiceHostFactory 15 | { 16 | private class AndiWebObjectActivatorAndiServiceProvider : IServiceProvider 17 | { 18 | public Object GetService( Type serviceType ) 19 | { 20 | return HttpRuntime.WebObjectActivator.GetService( serviceType ); 21 | } 22 | } 23 | 24 | private static readonly AndiWebObjectActivatorAndiServiceProvider _sp = new AndiWebObjectActivatorAndiServiceProvider(); 25 | 26 | /// Creates new instances with a custom that uses . 27 | protected override ServiceHost CreateServiceHost( Type serviceType, Uri[] baseAddresses ) 28 | { 29 | return new AndiWebServiceHost( serviceProvider: _sp, serviceType, baseAddresses ); 30 | } 31 | } 32 | 33 | /// Subclass of that adds new to every that allows access to the cutom passed into the constructor. 34 | public class AndiWebServiceHost : WebServiceHost 35 | { 36 | /// Initializes a new instance of the class with the specified and . The is used to extend 's . 37 | /// 38 | /// 39 | /// 40 | public AndiWebServiceHost( IServiceProvider serviceProvider, Type serviceType, params Uri[] baseAddresses ) 41 | : base( serviceType, baseAddresses ) 42 | { 43 | if( serviceProvider is null ) throw new ArgumentNullException(nameof(serviceProvider)); 44 | if( serviceType is null ) throw new ArgumentNullException(nameof(serviceType)); 45 | 46 | // 47 | 48 | ConstructorInfo[] ctors = serviceType.GetConstructors(); 49 | if( ctors.Length != 1 ) throw new InvalidOperationException( "Expected 1 public constructor for " + serviceType.FullName + "." ); 50 | 51 | foreach( ContractDescription contractDescription in this.ImplementedContracts.Values ) 52 | { 53 | // TODO: Is it one IInstanceProvider-per-Contract, or per-Injected service, or per-WCF service? 54 | contractDescription.ContractBehaviors.Add( new AndiInstanceProvider( serviceProvider ) ); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.WebApi/AspNetDependencyInjection.WebApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {4989D982-F9EC-4BC1-8288-7F25190AB725} 7 | Unity.WebForms.StrongNameKey.pfx 8 | 9 | 10 | 11 | Jehoel.AspNetDependencyInjection.WebApi 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {7e9e872b-41be-4b55-9519-d2ff3f92eb4e} 24 | AspNetDependencyInjection 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.WebApi/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | /* 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("AspNetDependencyInjection.WebApi")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("AspNetDependencyInjection.WebApi")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("4989d982-f9ec-4bc1-8288-7f25190ab725")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | [assembly: AssemblyVersion("4.0.*")] 38 | //[assembly: AssemblyFileVersion("1.0.0.0")] 39 | 40 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests, PublicKey=" + 41 | "0024000004800000940000000602000000240000525341310004000001000100b5644bd32f0714" + 42 | "dce56bb49d687880774726f85935f8213aff7d200ef6b75d6103996e8e26410b54475eeaeae3dd" + 43 | "3b1f48900025d8e66a8beb6c0580416ca82a0ef3ee4794dc2c06aa0d5e23ca5e4efaef2c98cc66" + 44 | "3efb5f00ef1c20b962a432e61dbbd5f672841d39de5b5ee2d157341d5d28a43c9bb7493ec838c8" + 45 | "e94586a5" )] 46 | */ 47 | 48 | [assembly: CLSCompliant(true)] 49 | -------------------------------------------------------------------------------- /AspNetDependencyInjection.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.31321.278 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{8D3132E8-858A-49E2-96A7-1F74FCEE2EF2}" 6 | ProjectSection(SolutionItems) = preProject 7 | nuget\AspNetDependencyInjection.nuspec = nuget\AspNetDependencyInjection.nuspec 8 | nuget\Build.cmd = nuget\Build.cmd 9 | GETTING_STARTED.md = GETTING_STARTED.md 10 | README.md = README.md 11 | EndProjectSection 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetDependencyInjection", "AspNetDependencyInjection\AspNetDependencyInjection.csproj", "{7E9E872B-41BE-4B55-9519-D2FF3F92EB4E}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetDependencyInjection.Tests", "AspNetDependencyInjection.Tests\AspNetDependencyInjection.Tests.csproj", "{7FF0B492-DEF1-4005-A899-0E82910481C4}" 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetDependencyInjection.Mvc", "AspNetDependencyInjection.Mvc\AspNetDependencyInjection.Mvc.csproj", "{1B4BE5D4-F919-44E9-B570-151EEE5698DA}" 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetDependencyInjection.WebApi", "AspNetDependencyInjection.WebApi\AspNetDependencyInjection.WebApi.csproj", "{4989D982-F9EC-4BC1-8288-7F25190AB725}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetDependencyInjection.SignalR", "AspNetDependencyInjection.SignalR\AspNetDependencyInjection.SignalR.csproj", "{7CB50365-9558-4CD9-98D1-7E33BDAAE15B}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetDependencyInjection.Wcf", "AspNetDependencyInjection.Wcf\AspNetDependencyInjection.Wcf.csproj", "{F1B12590-1707-4CB3-BA70-F6AE906E475D}" 24 | EndProject 25 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AEC64CF1-0DAB-4F30-8506-EC9290A199D0}" 26 | ProjectSection(SolutionItems) = preProject 27 | .editorconfig = .editorconfig 28 | Common.props = Common.props 29 | GETTING_STARTED.md = GETTING_STARTED.md 30 | README.md = README.md 31 | EndProjectSection 32 | EndProject 33 | Global 34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 35 | Debug|Any CPU = Debug|Any CPU 36 | Release|Any CPU = Release|Any CPU 37 | EndGlobalSection 38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 39 | {7E9E872B-41BE-4B55-9519-D2FF3F92EB4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {7E9E872B-41BE-4B55-9519-D2FF3F92EB4E}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {7E9E872B-41BE-4B55-9519-D2FF3F92EB4E}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {7E9E872B-41BE-4B55-9519-D2FF3F92EB4E}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {7FF0B492-DEF1-4005-A899-0E82910481C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {7FF0B492-DEF1-4005-A899-0E82910481C4}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {7FF0B492-DEF1-4005-A899-0E82910481C4}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {7FF0B492-DEF1-4005-A899-0E82910481C4}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {1B4BE5D4-F919-44E9-B570-151EEE5698DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {1B4BE5D4-F919-44E9-B570-151EEE5698DA}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {1B4BE5D4-F919-44E9-B570-151EEE5698DA}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {1B4BE5D4-F919-44E9-B570-151EEE5698DA}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {4989D982-F9EC-4BC1-8288-7F25190AB725}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {4989D982-F9EC-4BC1-8288-7F25190AB725}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {4989D982-F9EC-4BC1-8288-7F25190AB725}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {4989D982-F9EC-4BC1-8288-7F25190AB725}.Release|Any CPU.Build.0 = Release|Any CPU 55 | {7CB50365-9558-4CD9-98D1-7E33BDAAE15B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {7CB50365-9558-4CD9-98D1-7E33BDAAE15B}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {7CB50365-9558-4CD9-98D1-7E33BDAAE15B}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {7CB50365-9558-4CD9-98D1-7E33BDAAE15B}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {F1B12590-1707-4CB3-BA70-F6AE906E475D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {F1B12590-1707-4CB3-BA70-F6AE906E475D}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {F1B12590-1707-4CB3-BA70-F6AE906E475D}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {F1B12590-1707-4CB3-BA70-F6AE906E475D}.Release|Any CPU.Build.0 = Release|Any CPU 63 | EndGlobalSection 64 | GlobalSection(SolutionProperties) = preSolution 65 | HideSolutionNode = FALSE 66 | EndGlobalSection 67 | GlobalSection(NestedProjects) = preSolution 68 | EndGlobalSection 69 | GlobalSection(ExtensibilityGlobals) = postSolution 70 | SolutionGuid = {97C9B0E1-1AEE-40E1-B4B2-EFFDF47EED74} 71 | EndGlobalSection 72 | EndGlobal 73 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Configuration/AspNetDependencyInjectionConfigurationSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace AspNetDependencyInjection.Configuration 5 | { 6 | /// Defines the <AspNetDependencyInjection> configuration settings node inside an application configuration file. 7 | public class AspNetDependencyInjectionConfigurationSection : ConfigurationSection 8 | { 9 | /// Key for the configuration collection root element. 10 | private const String IgnoreNamespaceKeys = "ignoreNamspaces"; 11 | 12 | /// The name of the Section and configuration root node that contains the settings. 13 | public const String SectionPath = "AspNetDependencyInjection"; 14 | 15 | /// Collection of namespace prefixes to ignore for dependency injection. 16 | [ConfigurationProperty(IgnoreNamespaceKeys, IsDefaultCollection = false)] 17 | [ConfigurationCollection(typeof(NamespaceConfigurationElement), AddItemName = "namespace")] 18 | public IgnoreNamespaceConfigurationElementCollection Prefixes 19 | { 20 | get { return (IgnoreNamespaceConfigurationElementCollection)base[IgnoreNamespaceKeys]; } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Configuration/IgnoreNamespaceConfigurationElementCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace AspNetDependencyInjection.Configuration 5 | { 6 | /// 7 | /// Defines an optional custom 'ignoreNamespaces' collection that will 8 | /// contain the list of namspace prefixes to ignore when checking for 9 | /// dependencies to inject. 10 | /// 11 | #pragma warning disable CA1010 // Generic interface should also be implemented 12 | public class IgnoreNamespaceConfigurationElementCollection : ConfigurationElementCollection 13 | #pragma warning restore CA1010 14 | { 15 | /// Constructs and initializes a new instance of . 16 | public IgnoreNamespaceConfigurationElementCollection() 17 | { 18 | NamespaceConfigurationElement element = new NamespaceConfigurationElement(); 19 | this.BaseAdd( element, true ); 20 | } 21 | 22 | #region ConfigurationElementCollection implementation 23 | 24 | /// Gets the type of the System.Configuration.ConfigurationElementCollection. 25 | public override ConfigurationElementCollectionType CollectionType 26 | { 27 | get { return ConfigurationElementCollectionType.AddRemoveClearMap; } 28 | } 29 | 30 | /// Creates and returns a new object. 31 | protected override ConfigurationElement CreateNewElement() 32 | { 33 | return new NamespaceConfigurationElement(); 34 | } 35 | 36 | /// Gets the element key for the specified configuration element (). 37 | protected override Object GetElementKey( ConfigurationElement element ) 38 | { 39 | if( element is null ) throw new ArgumentNullException( nameof( element ) ); 40 | 41 | return ( (NamespaceConfigurationElement)element ).Prefix; 42 | } 43 | 44 | /// Adds the specified this System.Configuration.ConfigurationElementCollection. 45 | protected override void BaseAdd( ConfigurationElement element ) 46 | { 47 | this.BaseAdd( element, true ); 48 | } 49 | 50 | #endregion 51 | 52 | /// Returns the with the specified . 53 | public new NamespaceConfigurationElement this[String key] 54 | { 55 | get 56 | { 57 | return (NamespaceConfigurationElement)this.BaseGet( key ); 58 | } 59 | } 60 | 61 | /// Returns the index of the specified in this collection. 62 | public Int32 IndexOf( NamespaceConfigurationElement element ) 63 | { 64 | return this.BaseIndexOf( element ); 65 | } 66 | 67 | /// Adds the specified to the collection. 68 | public void Add( NamespaceConfigurationElement element ) 69 | { 70 | this.BaseAdd( element ); 71 | } 72 | 73 | /// Removes the specified from the collection. 74 | public void Remove( NamespaceConfigurationElement element ) 75 | { 76 | if( element is null ) throw new ArgumentNullException( nameof( element ) ); 77 | 78 | if( this.BaseIndexOf( element ) >= 0 ) 79 | { 80 | this.BaseRemove( element.Prefix ); 81 | } 82 | } 83 | 84 | /// Adds the at the specified . 85 | public void RemoveAt( Int32 index ) 86 | { 87 | this.BaseRemoveAt( index ); 88 | } 89 | 90 | /// Adds the with the specified . 91 | public void Remove( String key ) 92 | { 93 | this.BaseRemove( key ); 94 | } 95 | 96 | /// Removes all elements from this collection. 97 | public void Clear() 98 | { 99 | this.BaseClear(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Configuration/NamespaceConfigurationElement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | 4 | namespace AspNetDependencyInjection.Configuration 5 | { 6 | /// Defines an individual namespace element for exclusion when performing dependency injection. 7 | public class NamespaceConfigurationElement : ConfigurationElement 8 | { 9 | private const String PrefixKey = "prefix"; 10 | 11 | /// Initializes a new, empty, instance. 12 | public NamespaceConfigurationElement() 13 | { 14 | } 15 | 16 | /// Initializes a new instance with the supplied values. 17 | /// The namespace prefix to exclude from dependency injection. 18 | /// Thrown when is . 19 | /// When is not a valid namespace prefix. 20 | public NamespaceConfigurationElement( String prefix ) 21 | { 22 | _ = NamespacePrefix.ValidatePrefix( prefix ); // we don't care about the extracted result: we only care if it throws or not. 23 | 24 | this.Prefix = prefix; 25 | } 26 | 27 | /// The namespace prefix to exclude from injection scanning. This may include a leading ! and trailing .*. 28 | /// When the provided value is not a valid namespace prefix. 29 | [ConfigurationProperty( name: PrefixKey, DefaultValue = "System", IsKey = true, IsRequired = true )] 30 | [StringValidator( MinLength = 3, InvalidCharacters = NamespacePrefix.InvalidChars )] 31 | public String Prefix 32 | { 33 | get { return (String)this[PrefixKey]; } 34 | set 35 | { 36 | _ = NamespacePrefix.ValidatePrefix( value ); // As with the ctor, provided that `ValidatePrefix` doesn't throw then it's okay. 37 | this[PrefixKey] = value; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Configuration/NamespacePrefix.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | 6 | namespace AspNetDependencyInjection.Configuration 7 | { 8 | /// Represents a CLR namespace prefix selector. If a prefix is `MyCompany.MyProduct` then it will match `MyCompany.MyProduct` and `MyCompany.MyProduct.Component` (a child namespace) but not `MyCompany.MyProducts` (as that is a different namespace at the same level). 9 | [DebuggerDisplay("Namespace = {Value}, Exclude = {Exclude}")] 10 | public class NamespacePrefix 11 | { 12 | #region Static 13 | 14 | private static readonly Char[] _trimStartChars = new Char[] { '!' }; 15 | private static readonly Char[] _trimEndChars = new Char[] { '*', '.' }; 16 | 17 | internal const String InvalidChars = "!@#$%^&*()+=[{]}\\|;:'\",<>/?~`"; 18 | 19 | private static readonly HashSet _invalidChars = new HashSet( InvalidChars ); 20 | 21 | /// Verifies that is a syntactically valid .NET namespace prefix name and returns it if it is valid, otherwise it throws an if is invalid. 22 | /// A .NET namespace name. The value may have a Java-style package import suffix (".*") which will be trimmed away. 23 | /// Thrown when is . 24 | /// Thrown when is invalid. 25 | public static ( String ns, Boolean exclude, Boolean isGlob ) ValidatePrefix( String prefix ) 26 | { 27 | if( String.IsNullOrWhiteSpace( prefix ) ) throw new ArgumentNullException(nameof(prefix)); 28 | 29 | prefix = prefix.Trim(); // Trim only whitespace first. 30 | 31 | Boolean exclude = prefix[0] == '!'; 32 | Boolean isGlob = prefix[ prefix.Length - 1 ] == '*'; 33 | 34 | prefix = prefix.TrimStart( _trimStartChars ); 35 | prefix = prefix.TrimEnd ( _trimEndChars ); // e.g. so if `prefix == "MyCompany.MyProduct.*` it becomes `MyCompany.MyProduct`. 36 | 37 | if( String.IsNullOrWhiteSpace( prefix ) ) throw new ArgumentException( message: "Namespace was empty or white-space after trimming.", paramName: nameof(prefix) ); 38 | 39 | if( prefix.Any( c => _invalidChars.Contains( c ) || Char.IsWhiteSpace( c ) ) ) throw new ArgumentException( message: "Value contains an invalid character or whitespace.", paramName: nameof(prefix) ); 40 | if( prefix.IndexOf( "..", StringComparison.Ordinal ) > -1 ) throw new ArgumentException( message: "Value contains an empty namespace name.", paramName: nameof(prefix) ); 41 | 42 | return ( prefix, exclude, isGlob ); 43 | } 44 | 45 | #endregion 46 | 47 | /// Constructs a new object after first validating the provided prefix value. Throws if the prefix is syntactically invalid. For more information see the documentation for . 48 | /// A .NET namespace name. The value may have a Java-style package import suffix (".*") which will be trimmed away. 49 | public NamespacePrefix( String prefix ) 50 | { 51 | ( String ns, Boolean exclude, Boolean isGlob ) = ValidatePrefix( prefix ); 52 | 53 | this.Length = prefix.Count( c => c == '.' ) + 1; 54 | this.Value = ns; 55 | this.Exclude = exclude; 56 | 57 | this.IsDefinitelyGlob = isGlob; 58 | } 59 | 60 | /// The depth of this namespace prefix. A single name, e.g. System and System.* are 1 (they're equivalent), System.Web is 2, System.Web.Foobar and System.Web.Barbaz.* are both 3, and so on. 61 | public Int32 Length { get; } 62 | 63 | /// Gets the validated prefix input passed into the constructor. 64 | public String Value { get; } 65 | 66 | /// When a configured rule starts with '!' then the rule is negated and the fully-qualified-type-name to test will not be matched. 67 | public Boolean Exclude { get; } 68 | 69 | /// If the source input pattern was a glob (ended in a wildcard). Note that a namespace name will not be a glob even though it is a prefix... so only use this to exclude definitely-globs from exact-type-name matches. 70 | public Boolean IsDefinitelyGlob { get; } 71 | 72 | /// Returns true if this namespace prefix matches the specified type full name (i.e. the specified type's exists in a namespace that is matched by this prefix. Otherwise returns false.> 73 | public Boolean Matches( String typeName ) 74 | { 75 | if( String.IsNullOrWhiteSpace( typeName ) ) throw new ArgumentNullException(nameof(typeName)); 76 | 77 | if( typeName.StartsWith( this.Value, StringComparison.Ordinal ) ) 78 | { 79 | if( typeName.Length == this.Value.Length ) return true; 80 | 81 | Char expectedDot = typeName[ this.Value.Length ]; 82 | return expectedDot == '.'; 83 | } 84 | else 85 | { 86 | return false; 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/DependencyInjectionOverrides/IDependencyInjectionOverrideService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AspNetDependencyInjection 4 | { 5 | /// Informs which service-types should not be created using the configured and should instead always be constructed using ASP.NET's default activator (as though no were set). 6 | public interface IDependencyInjectionOverrideService 7 | { 8 | /// Returns the for the specified service . Returns false if the specified service should be provided by the configured AspNetDependencyInjection. 9 | Boolean TryGetServiceProvider( Type serviceType, out IServiceProvider serviceProvider ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/DependencyInjectionOverrides/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.DependencyInjection.Extensions; 6 | 7 | using AspNetDependencyInjection.Services; 8 | 9 | namespace AspNetDependencyInjection 10 | { 11 | /// Extension methods for services bundled with . 12 | [CLSCompliant(false)] // IServiceCollection is not CLS-compliant. 13 | public static partial class ServiceCollectionExtensions 14 | { 15 | /// Registers as a singleton implementation of . 16 | public static IServiceCollection AddDefaultDependencyInjectionOverrideService( this IServiceCollection services, Boolean excludeAspNetNamespacesFromDI = true, IEnumerable additionalExclusions = null ) 17 | { 18 | return services 19 | .AddSingleton( sp => new DefaultDependencyInjectionOverrideService( useConfigured: true, excludeAspNetNamespacesFromDI, additionalExclusions ) ); 20 | } 21 | 22 | /// Registers as a singleton implementation of if no existing implementation of is registered. 23 | public static void TryAddDefaultDependencyInjectionOverrideService( this IServiceCollection services ) 24 | { 25 | services 26 | .TryAddSingleton( sp => new DefaultDependencyInjectionOverrideService( useConfigured: true, excludeAspNetNamespacesFromDI: true, additionalExclusions: null ) ); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/HttpContextAccessor/HttpContextAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | namespace AspNetDependencyInjection.Services 5 | { 6 | /// Gets the for the current request in a thread-safe manner (by using an immutable instance field reference to the available when the request was started). 7 | public class DefaultHttpContextAccessor : IHttpContextAccessor 8 | { 9 | /// Constructs a new instance of using the provided . 10 | /// Required. Cannot be null (otherwise an will be thrown). 11 | public DefaultHttpContextAccessor( HttpContextBase httpContextBase ) 12 | { 13 | this.HttpContext = httpContextBase ?? throw new ArgumentNullException(nameof(httpContextBase)); 14 | } 15 | 16 | /// Always returns the same instance that was passed into this instance's constructor (i.e. it does not use ). 17 | public HttpContextBase HttpContext { get; } 18 | } 19 | 20 | // NOTE: When would *anyone* ever want to use `ThreadLocalStorageHttpContextAccessor`? That's why this is disabled. 21 | // If those types need some form of compatibility with the thread-unsafe `HttpContext.Current` then they can use it directly. 22 | 23 | #if ANY_GOOD_REASONS_FOR_THIS 24 | 25 | /// Implements by simply returning wrapped in a new . 26 | public class ThreadLocalStorageHttpContextAccessor : IHttpContextAccessor 27 | { 28 | /// Always returns new HttpContextWrapper( System.Web.HttpContext.Current ). 29 | public HttpContextBase HttpContext 30 | { 31 | get 32 | { 33 | return new HttpContextWrapper( System.Web.HttpContext.Current ); 34 | } 35 | } 36 | } 37 | 38 | #endif 39 | } 40 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/HttpContextAccessor/IHttpContextAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using System.Web; 8 | 9 | namespace AspNetDependencyInjection 10 | { 11 | /// Implementations are always request-scoped. This service allows consumers to get the for the current request. 12 | public interface IHttpContextAccessor 13 | { 14 | /// 15 | /// Gets the for the current request.
16 | /// Implementations will use a strong-reference to the associated with the current HTTP request instead of using (which uses thread-local-storage), which means that references can be safely passed around to other threads.
17 | /// To get the "classic" from a , use . 18 | ///
19 | HttpContextBase HttpContext { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/HttpContextAccessor/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | using AspNetDependencyInjection.Services; 7 | using AspNetDependencyInjection.Internal; 8 | 9 | namespace AspNetDependencyInjection 10 | { 11 | public static partial class ServiceCollectionExtensions 12 | { 13 | /// Creates a scoped service implementation for that uses a hard reference to (i.e. it does not use ). 14 | [CLSCompliant(false)] 15 | public static IServiceCollection AddDefaultHttpContextAccessor( this IServiceCollection services ) 16 | { 17 | if( services is null ) throw new ArgumentNullException(nameof(services)); 18 | 19 | return services 20 | .AddScoped() 21 | .AddScoped( CreateHttpContextAccessor ); 22 | } 23 | 24 | /// Use this extension method if you wish to use your own logic for getting or creating a HttpContext for services without reimplementing directly. 25 | [CLSCompliant(false)] 26 | public static IServiceCollection AddCustomHttpContextAccessor( this IServiceCollection services, Func httpContextGetter ) 27 | { 28 | if( services is null ) throw new ArgumentNullException(nameof(services)); 29 | if( httpContextGetter is null ) throw new ArgumentNullException(nameof(httpContextGetter)); 30 | 31 | return services 32 | .AddScoped( sp => CreateCustomHttpContextAccessor( sp, httpContextGetter ) ); 33 | } 34 | 35 | private static IHttpContextAccessor CreateHttpContextAccessor( IServiceProvider sp ) 36 | { 37 | DefaultHttpContextAccessorHelper helper = sp.GetRequiredService(); 38 | if( helper.HttpContext is null ) throw new InvalidOperationException( "The " + nameof(HttpContextBase) + " has not been set for this Service Scope." ); 39 | 40 | return new DefaultHttpContextAccessor( helper.HttpContext ); 41 | } 42 | 43 | private static IHttpContextAccessor CreateCustomHttpContextAccessor( IServiceProvider sp, Func httpContextGetter ) 44 | { 45 | HttpContextBase httpContext = httpContextGetter( sp ); 46 | if( httpContext is null ) throw new InvalidOperationException( "The configured " + nameof(HttpContextBase) + " getter function returned null." ); 47 | 48 | return new DefaultHttpContextAccessor( httpContext ); 49 | } 50 | } 51 | } 52 | 53 | namespace AspNetDependencyInjection.Internal 54 | { 55 | #pragma warning disable CA1812 // Avoid uninstantiated internal classes // This class is instantiated by DI. 56 | internal class DefaultHttpContextAccessorHelper 57 | { 58 | public HttpContextBase HttpContext { get; set; } 59 | } 60 | #pragma warning restore 61 | } 62 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/ServiceFactory/IServiceFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace AspNetDependencyInjection 6 | { 7 | /// An interface for service factories to implement for use with . 8 | /// The type of service that implementations will produce. 9 | public interface IServiceFactory 10 | { 11 | /// Creates a new instance of . 12 | TService CreateInstance(); 13 | } 14 | 15 | public static partial class ServiceCollectionExtensions 16 | { 17 | /// Convenience method that registers twice: first as AddSingleton<TServiceFactory> and again as AddSingleton<IServiceFactory<TService>,TServiceFactory>, then and registers as a Scoped service that uses as a factory. 18 | public static IServiceCollection AddScopedWithFactory( this IServiceCollection services ) 19 | where TService : class 20 | where TServiceFactory : class, IServiceFactory 21 | { 22 | return services 23 | .AddSingleton() 24 | .AddSingleton,TServiceFactory>() 25 | .AddScoped( implementationFactory: sp => sp.GetRequiredService().CreateInstance() ); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/ServiceProviderAccessor/DefaultServiceProviderAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AspNetDependencyInjection.Services 4 | { 5 | /// Provides access to the root . 6 | public class DefaultServiceProviderAccessor : IServiceProviderAccessor 7 | { 8 | /// Constructs a new instance of . 9 | public DefaultServiceProviderAccessor( ImmutableApplicationDependencyInjectionConfiguration configuration, IServiceProvider rootServiceProvider ) 10 | { 11 | this.Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); 12 | this.RootServiceProvider = rootServiceProvider ?? throw new ArgumentNullException(nameof(rootServiceProvider)); 13 | } 14 | 15 | /// Exposes 's . 16 | public ImmutableApplicationDependencyInjectionConfiguration Configuration { get; } 17 | 18 | /// The root configured during startup. 19 | public IServiceProvider RootServiceProvider { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/ServiceProviderAccessor/IServiceProviderAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AspNetDependencyInjection 4 | { 5 | /// Allows objects to have a dependency on the root in the application. 6 | public interface IServiceProviderAccessor 7 | { 8 | /// Immutable copy of the configuration passed into . 9 | ImmutableApplicationDependencyInjectionConfiguration Configuration { get; } 10 | 11 | /// Gets the root in this AppDomain. It is managed by . 12 | IServiceProvider RootServiceProvider { get; } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/WebConfiguration/DefaultWebConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Configuration; 5 | using System.Linq; 6 | using System.Web.Configuration; 7 | 8 | namespace AspNetDependencyInjection.Services 9 | { 10 | /// Implementation of that populates itself using 's static properties. The dictionaries have case-insensitive keys. 11 | /// This class is designed to assist applications with shifting towards appSettings.json-type config used in ASP.NET Core - the idea being to use Dictionary-style configuration in WebForms first, then it's one less thing to fix when everything is broken immediately after migrating to ASP.NET Core. 12 | public class DefaultWebConfiguration : IWebConfiguration 13 | { 14 | /// Constructs a new instance of that sets the and collection properties to immutable snapshot copies of 's respective static collection properties. 15 | public DefaultWebConfiguration() 16 | { 17 | this.AppSettings = AndiExtensions.ToDictionary( WebConfigurationManager.AppSettings ); 18 | 19 | this.ConnectionStrings = WebConfigurationManager.ConnectionStrings 20 | .OfType() 21 | .ToDictionary( cs => cs.Name, comparer: StringComparer.OrdinalIgnoreCase ); 22 | } 23 | 24 | /// Provides read-only access to a snapshot copy of . The dictionary uses a case-insensitive key comparer. 25 | public IReadOnlyDictionary AppSettings { get; } 26 | 27 | /// Provides read-only access to a snapshot copy of . The dictionary uses a case-insensitive key comparer. 28 | public IReadOnlyDictionary ConnectionStrings { get; } 29 | 30 | /// Returns an representation of a .NET configuration section provided by either , , or (or any configuration section that is resolvable to or ). Returns null if the section does not exist. 31 | /// Unlike the and properties of values are not eagerly-loaded inside 's constructor. 32 | public IReadOnlyDictionary GetKeyValueSection( String sectionName ) 33 | { 34 | if( String.IsNullOrWhiteSpace(sectionName) ) throw new ArgumentNullException(nameof(sectionName)); 35 | 36 | // 37 | 38 | Object sectionObj = WebConfigurationManager.GetSection( sectionName ); 39 | if( sectionObj is null ) return null; 40 | 41 | if( sectionObj is IReadOnlyDictionary rodict ) 42 | { 43 | return rodict; 44 | } 45 | else if( sectionObj is System.Collections.Hashtable hashtable ) 46 | { 47 | return hashtable.Keys 48 | .Cast() 49 | .Select( keyObj => ( key: keyObj as String, value: hashtable[keyObj] as String ) ) 50 | .Where( t => t.key != null ) 51 | .ToDictionary( t => t.key, t => t.value, comparer: StringComparer.OrdinalIgnoreCase ); 52 | 53 | } 54 | else if( sectionObj is System.Collections.IDictionary dict ) 55 | { 56 | return dict.Keys 57 | .Cast() 58 | .Select( keyObj => ( key: keyObj as String, value: dict[keyObj] as String ) ) 59 | .Where( t => t.key != null ) 60 | .ToDictionary( t => t.key, t => t.value, comparer: StringComparer.OrdinalIgnoreCase ); 61 | } 62 | else if( sectionObj is NameValueCollection nvc ) 63 | { 64 | return AndiExtensions.ToDictionary( nvc ); 65 | } 66 | else 67 | { 68 | throw new InvalidOperationException( "The configuration section named \"" + sectionName + "\" is of type " + sectionObj.GetType().FullName + " and cannot be converted to an " + nameof(IReadOnlyDictionary) + "." ); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/WebConfiguration/IWebConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Configuration; 5 | using System.Web.Configuration; 6 | 7 | namespace AspNetDependencyInjection 8 | { 9 | /// Provides an injectable representation of that can be mocked for testing. 10 | public interface IWebConfiguration 11 | { 12 | /// Provides read-only access to . The dictionary uses a case-insensitive key comparer. 13 | /// WebConfigurationManager returns a which allows multiple values for a key, whereas the <appSettings> element does not allow duplicate keys - hence why this property returns a . 14 | IReadOnlyDictionary AppSettings { get; } 15 | 16 | /// Provides read-only access to . The dictionary uses a case-insensitive key comparer. 17 | IReadOnlyDictionary ConnectionStrings { get; } 18 | 19 | /// Returns an representation of a .NET configuration section provided by either , , or (or any configuration section that is resolvable to or ). Returns null if the section does not exist. 20 | /// Thrown when the refers to a section that cannot be converted to an . 21 | IReadOnlyDictionary GetKeyValueSection( String sectionName ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/WebConfiguration/PassthroughWebConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | 5 | namespace AspNetDependencyInjection.Services 6 | { 7 | /// Implements using values passed to its constructor. Intended for testing purposes. For production use in an ASP.NET environment, use . 8 | public class PassthroughWebConfiguration : IWebConfiguration 9 | { 10 | private readonly IReadOnlyDictionary> otherSections; 11 | 12 | /// Constructs a instance using provided values only. Intended for testing purposes. 13 | /// Required. Cannot be null otherwise is thrown. 14 | /// Required. Cannot be null otherwise is thrown. 15 | /// Optional. Member dictionaries are returned by . 16 | public PassthroughWebConfiguration( IReadOnlyDictionary appSettings, IReadOnlyDictionary connectionStrings, IReadOnlyDictionary> otherSections = null ) 17 | { 18 | // TOOD: Is there a way to check the type of comparer an IReadOnlyDictionary is using to ensure it's case-insensitive? 19 | 20 | this.AppSettings = appSettings ?? throw new ArgumentNullException(nameof(appSettings)); 21 | this.ConnectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); 22 | this.otherSections = otherSections; 23 | } 24 | 25 | /// The dictionary's key comparer is undefined and may not be case-insensitive. 26 | public IReadOnlyDictionary AppSettings { get; } 27 | 28 | /// The dictionary's key comparer is undefined and may not be case-insensitive. 29 | public IReadOnlyDictionary ConnectionStrings { get; } 30 | 31 | /// Gets a dictionary from the otherSections dictionary passed into this object's constructor. Returns if the section doesn't exist. 32 | public IReadOnlyDictionary GetKeyValueSection( String sectionName ) 33 | { 34 | if( this.otherSections == null ) return null; 35 | 36 | return this.otherSections.TryGetValue( sectionName, out IReadOnlyDictionary section ) ? section : null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.Services/WebConfiguration/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 |  2 | using AspNetDependencyInjection.Services; 3 | 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace AspNetDependencyInjection 7 | { 8 | /// Extension methods for services bundled with . 9 | public static partial class ServiceCollectionExtensions 10 | { 11 | /// Registers as a singleton implementation of . 12 | public static IServiceCollection AddWebConfiguration( this IServiceCollection services ) 13 | { 14 | return services 15 | .AddSingleton(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {7E9E872B-41BE-4B55-9519-D2FF3F92EB4E} 7 | Unity.WebForms.StrongNameKey.pfx 8 | $(DefineConstants);ISSUE9; 9 | 10 | 11 | 12 | Jehoel.AspNetDependencyInjection 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection/ActivatorServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace AspNetDependencyInjection.Internal 5 | { 6 | /// Does not perform any caching or object lifetime management - everything is transient. 7 | internal class ActivatorServiceProvider : IServiceProvider 8 | { 9 | public static ActivatorServiceProvider Instance { get; } = new ActivatorServiceProvider(); 10 | 11 | private ActivatorServiceProvider() 12 | { 13 | } 14 | 15 | public Object GetService( Type serviceType ) 16 | { 17 | return this.GetService( serviceType: serviceType, args: null ); 18 | } 19 | 20 | #pragma warning disable CA1822 // Mark members as static 21 | public Object GetService( Type serviceType, params Object[] args ) 22 | #pragma warning restore CA1822 23 | { 24 | return Activator.CreateInstance( 25 | type : serviceType, 26 | bindingAttr : BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance, 27 | binder : null, 28 | args : args, 29 | culture : null, 30 | activationAttributes: null 31 | ); 32 | } 33 | } 34 | 35 | /// Always returns null in calls to . 36 | internal class NullServiceProvider : IServiceProvider 37 | { 38 | public static NullServiceProvider Instance { get; } = new NullServiceProvider(); 39 | 40 | public Object GetService(Type serviceType) 41 | { 42 | return null; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection/ApplicationDependencyInjectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Web; 4 | 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | namespace AspNetDependencyInjection 8 | { 9 | /// Controls for . 10 | public class ApplicationDependencyInjectionConfiguration 11 | { 12 | /// 13 | /// This property is by default.
14 | /// When , a new will be created for each instance (i.e. for each new HTTP request/response lifecycle).
15 | /// When all instances will use the parent , which may be the root service-provider or may be from the parent (when is true. 16 | ///
17 | public Boolean UseRequestScopes { get; set; } = true; 18 | 19 | /// This property is by default.
20 | /// When , a new will be created for each instance: this may be desirable if you have services that are not thread-safe.
21 | /// When all instances will use the root directly. For best performance, your Global.asax class should implement to allow for storage of the , otherwise reflection will be used to store it inside a Hashtable inside each instance.
22 | public Boolean UseHttpApplicationScopes { get; set; } 23 | 24 | /// Returns an instance of with a copy of all members of this object. May return a subclass in an overriden implementation. 25 | protected internal virtual ImmutableApplicationDependencyInjectionConfiguration ToImmutable() 26 | { 27 | return new ImmutableApplicationDependencyInjectionConfiguration( useRequestScopes: this.UseRequestScopes, useHttpApplicationScopes: this.UseHttpApplicationScopes ); 28 | } 29 | } 30 | 31 | /// Immutable copy of . 32 | public class ImmutableApplicationDependencyInjectionConfiguration 33 | { 34 | /// Constructor. 35 | public ImmutableApplicationDependencyInjectionConfiguration( Boolean useRequestScopes, Boolean useHttpApplicationScopes ) 36 | { 37 | this.UseRequestScopes = useRequestScopes; 38 | this.UseHttpApplicationScopes = useHttpApplicationScopes; 39 | } 40 | 41 | /// See . 42 | public Boolean UseRequestScopes { get; } 43 | 44 | /// See . 45 | public Boolean UseHttpApplicationScopes { get; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection/DependencyInjectionWebObjectActivator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | namespace AspNetDependencyInjection.Internal 5 | { 6 | /// Implementation of intended for use ONLY as . The behaviour of always returns a requested type or throws an exception. 7 | /// While this class implements it is not intended to be used as a DI service-provider for use with Microsoft.Extensions.DependencyInjection - it is only so it can be used with . 8 | public sealed class DependencyInjectionWebObjectActivator : IServiceProvider, IDependencyInjectionClient 9 | { 10 | private readonly ApplicationDependencyInjection di; 11 | 12 | /// Instantiates a new instance of . You do not need to normally use this constructor directly - instead use . 13 | /// Required. 14 | public DependencyInjectionWebObjectActivator( ApplicationDependencyInjection di ) 15 | { 16 | this.di = di ?? throw new ArgumentNullException(nameof(di)); 17 | 18 | HttpRuntime.WebObjectActivator = this; 19 | } 20 | 21 | /// Gets the service object of the specified type from the current . This method should ONLY be called by ASP.NET's infrastructure via . This method never returns a object reference and will throw an exception if resolution fails. 22 | // IMPORTANT NOTE: This method MUST return an instantiated serviceType - or throw an exception. i.e. it cannot return null - so if the root IServiceProvider returns null then fallback to (completely different serviceProviders) - otherwise throw. 23 | public Object GetService( Type serviceType ) 24 | { 25 | return this.di.ObjectFactoryCache.GetRequiredService( this.GetServiceProviderForCurrentHttpContext, serviceType, useOverrides: true ); 26 | } 27 | 28 | private IServiceProvider GetServiceProviderForCurrentHttpContext() 29 | { 30 | // As WebObjectActivator will always be called from an ASP.NET Request-Thread-Pool-thread, HttpContext.Current *should* always be non-null. 31 | HttpContext httpContext = HttpContext.Current; 32 | if( httpContext is null ) throw new InvalidOperationException( "HttpContext.Current is null." ); // This should never happen, provided only ASP.NET is using `DependencyInjectionWebObjectActivator`. 33 | 34 | return this.di.GetServiceProviderForHttpContext( httpContext ); 35 | } 36 | 37 | /// Unsets only if its value is this instance. 38 | public void Dispose() 39 | { 40 | if( Object.ReferenceEquals( HttpRuntime.WebObjectActivator, this ) ) 41 | { 42 | HttpRuntime.WebObjectActivator = null; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | 5 | namespace AspNetDependencyInjection 6 | { 7 | /// Provides extension methods for . 8 | public static class AndiExtensions 9 | { 10 | /// Returns a new that refers to a concrete generic where T is . 11 | public static Type ToIEnumerableOf( this Type serviceType ) 12 | { 13 | if( serviceType is null ) throw new ArgumentNullException(nameof(serviceType)); 14 | 15 | // 16 | 17 | // See `Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions`: 18 | Type closedGenericType = typeof(IEnumerable<>).MakeGenericType( serviceType ); 19 | return closedGenericType; 20 | } 21 | 22 | /// Calls and passes it into and casts the result as where T is . 23 | public static IEnumerable ToIEnumerableOf( this Type serviceType, Func getService ) 24 | { 25 | if( serviceType is null ) throw new ArgumentNullException(nameof(serviceType)); 26 | if( getService is null ) throw new ArgumentNullException(nameof(getService)); 27 | 28 | // 29 | 30 | Type enumerableOf = ToIEnumerableOf( serviceType ); 31 | Object result = getService( enumerableOf ); 32 | return (IEnumerable)result; 33 | } 34 | 35 | /// 36 | /// Converts into a (of String Keys and String values).
37 | /// If returns multiple values for any name/key, then only the first value returned will be added to the returned dictionary.
38 | /// The returned dictionary will use to compare keys. 39 | ///
40 | public static Dictionary ToDictionary( NameValueCollection nvc ) 41 | { 42 | if( nvc is null ) throw new ArgumentNullException( nameof( nvc ) ); 43 | 44 | Dictionary dict = new Dictionary( capacity: nvc.Count, comparer: StringComparer.OrdinalIgnoreCase ); 45 | 46 | foreach( String key in nvc.Keys ) 47 | { 48 | String firstValue = nvc.GetValues( key )[0]; 49 | dict[ key ] = firstValue; 50 | } 51 | 52 | return dict; 53 | } 54 | /// Gets a "classic" from a via httpContextBase.ApplicationInstance.Context 55 | public static System.Web.HttpContext GetHttpContext( this System.Web.HttpContextBase httpContextBase ) 56 | { 57 | if( httpContextBase is null ) throw new ArgumentNullException( nameof( httpContextBase ) ); 58 | 59 | // These conditions should never happen, but just-in-case: 60 | if( httpContextBase.ApplicationInstance is null ) throw new ArgumentException( message: "httpContextBase.ApplicationInstance is null." , paramName: nameof( httpContextBase ) ); 61 | if( httpContextBase.ApplicationInstance.Context is null ) throw new ArgumentException( message: "httpContextBase.ApplicationInstance.Context is null.", paramName: nameof( httpContextBase ) ); 62 | 63 | return httpContextBase.ApplicationInstance.Context; 64 | } 65 | 66 | /// Gets a from a "classic" via httpContext.Request.RequestContext.HttpContext 67 | public static System.Web.HttpContextBase GetHttpContextBase( this System.Web.HttpContext httpContext ) 68 | { 69 | if( httpContext is null ) throw new ArgumentNullException( nameof( httpContext ) ); 70 | 71 | // These conditions should never happen, but just-in-case: 72 | if( httpContext.Request is null ) throw new ArgumentException( message: "httpContext.Request is null." , paramName: nameof( httpContext ) ); 73 | if( httpContext.Request.RequestContext is null ) throw new ArgumentException( message: "httpContext.Request.RequestContext is null." , paramName: nameof( httpContext ) ); 74 | if( httpContext.Request.RequestContext.HttpContext is null ) throw new ArgumentException( message: "httpContext.Request.RequestContext.HttpContext is null.", paramName: nameof( httpContext ) ); 75 | 76 | return httpContext.Request.RequestContext.HttpContext; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/AspNetDependencyInjection/IDependencyInjectionClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace AspNetDependencyInjection 5 | { 6 | /// Denotes a class that will be disposed when the associated object is disposed. This is intended for use by classes that wrap to provide or adapt DI services for non-MEDI consumers, for example, ASP.NET MVC, ASP.NET SignalR, and ASP.NET Web API all have their own separate DI resolver systems. 7 | public interface IDependencyInjectionClient : IDisposable 8 | { 9 | } 10 | } 11 | 12 | namespace AspNetDependencyInjection.Internal 13 | { 14 | /// Exposes the (live, not snapshotted) collection of registrations in . This interface is intended for testing purposes (without needing to use , which is painful to use with strong-name signed assemblies). 15 | public interface IHasDependencyInjectionClients 16 | { 17 | /// Returns the (live, not snapshotted) collection of registrations. 18 | IReadOnlyList Clients { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AspNetDependencyInjection/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.InteropServices; 6 | 7 | /* 8 | [assembly: AssemblyTitle( "AspNetDependencyInjection" )] 9 | [assembly: AssemblyDescription( "Dependency Injection in \"Classic\" ASP.NET using Microsoft.Extensions.DependencyInjection." )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "AspNetDependencyInjection" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2013 - 2019 S. Kyle Korndoerfer, Dai Rees (@Jehoel on GitHub)" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | [assembly: NeutralResourcesLanguage( "en-US" )] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible( false )] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid( "26a7c154-c919-4169-bf4e-702aa5398e1c" )] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion( "4.0.*" )] 37 | //[assembly: AssemblyFileVersion( "2.0.0.0" )] 38 | 39 | // Version 1.x = S. Kyle Korndoerfer's Unity.WebForms. 40 | // Version 2.x = Jehoel's Unity.WebForms using WebObjectActivator. 41 | // Version 3.x = AspNetDependencyInjection using Microsoft.Extensions.DependencyInjection. 42 | // Version 4.x = AspNetDependencyInjection using Microsoft.Extensions.DependencyInjection. 43 | 44 | */ 45 | 46 | /* 47 | 48 | #if DEBUG 49 | 50 | //[assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests" )] 51 | 52 | #else 53 | 54 | [assembly: InternalsVisibleTo( assemblyName: @"AspNetDependencyInjection.Tests, PublicKey=" + 55 | "0024000004800000940000000602000000240000525341310004000001000100b5644bd32f0714" + 56 | "dce56bb49d687880774726f85935f8213aff7d200ef6b75d6103996e8e26410b54475eeaeae3dd" + 57 | "3b1f48900025d8e66a8beb6c0580416ca82a0ef3ee4794dc2c06aa0d5e23ca5e4efaef2c98cc66" + 58 | "3efb5f00ef1c20b962a432e61dbbd5f672841d39de5b5ee2d157341d5d28a43c9bb7493ec838c8" + 59 | "e94586a5" )] 60 | 61 | #endif 62 | 63 | */ 64 | 65 | [assembly: CLSCompliant(true)] 66 | -------------------------------------------------------------------------------- /Common.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | 7.3 6 | true 7 | true 8 | true 9 | 10 | embedded 11 | 12 | 13 | 14 | 15 | 16 | AspNetDependencyInjection 17 | 18 | 19 | 20 | true 21 | AllEnabledByDefault 22 | 25 | 26 | 27 | 28 | 5.0.0-beta3 29 | 30 | Dependency Injection in "Classic" ASP.NET WebForms, ASP.NET MVC, ASP.NET Web API, and ASP.NET-hosted WCF using Microsoft.Extensions.DependencyInjection. 31 | Unity ASP.NET WebForms Dependency Injection IoC DI WebObjectActivator constructor Microsoft.Extensions.DependencyInjection medi Microsoft.Extensions.Logging container 32 | 2013 - 2021 Contributors 33 | 34 | 35 | Dai Rees (@Jehoel on GitHub), S. Kyle Korndoerfer (@KyKoSoft on NuGet), Contributors 36 | 37 | 38 | Jehoel, KyKoSoft 39 | 40 | 41 | MIT 42 | https://github.com/Jehoel/AspNetDependencyInjection 43 | true 44 | snupkg 45 | 46 | 47 | 48 | Unity.WebForms.StrongNameKey.pfx 49 | true 50 | true 51 | 52 | 53 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 S. Kyle Korndoerfer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/App_Start/AppStartup.cs: -------------------------------------------------------------------------------- 1 | #define USE_SCOPED_SIGNALR_RESOLVER 2 | 3 | using System; 4 | 5 | using Microsoft.AspNet.SignalR; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | using Owin; 9 | using Microsoft.Owin; 10 | using AspNetDependencyInjection; 11 | using WebActivatorEx; 12 | 13 | using SampleMvcWebApplication; 14 | using SampleMvcWebApplication.SampleServices; 15 | 16 | [assembly: PreApplicationStartMethod ( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PreStart ) )] 17 | [assembly: PostApplicationStartMethod( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PostStart ) )] 18 | [assembly: ApplicationShutdownMethod ( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.ApplicationShutdown ) )] 19 | 20 | [assembly: OwinStartup( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.OwinStartup ) )] 21 | 22 | namespace SampleMvcWebApplication 23 | { 24 | /// Startup class for the AspNetDependencyInjection NuGet package. 25 | internal static class SampleApplicationStart 26 | { 27 | private static ApplicationDependencyInjection _di; 28 | 29 | /// Invoked when the ASP.NET application starts up, before Global's Application_Start method runs. Dependency-injection should be configured here. 30 | internal static void PreStart() 31 | { 32 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PreStart) + "() called." ); 33 | 34 | // If you are using ASP.NET Web Forms without any ASP.NET MVC functionality, remove the call to `.AddMvcDependencyResolver()`. 35 | // If you are using ASP.NET MVC, regardless of whether you're using ASP.NET Web Forms, use `.AddMvcDependencyResolver()`: 36 | 37 | _di = new ApplicationDependencyInjectionBuilder() 38 | .ConfigureServices( ConfigureServices ) 39 | .AddMvcDependencyResolver() 40 | #if USE_SCOPED_SIGNALR_RESOLVER 41 | .AddScopedSignalRDependencyResolver() 42 | #else 43 | .AddUnscopedSignalRDependencyResolver() 44 | #endif 45 | .Build(); 46 | } 47 | 48 | private static void ConfigureServices( IServiceCollection services ) 49 | { 50 | // TODO: Add any dependencies needed here 51 | _ = services 52 | // Useful services built-in to AspNetDependencyInjection: 53 | .AddDefaultHttpContextAccessor() // Adds `IHttpContextAccessor` 54 | .AddWebConfiguration() // Adds `IWebConfiguration` 55 | .AddSingleton() // `IUserIdProvider` is a SignalR built-in service. SignalR's `PrincipalUserIdProvider` (the default implementation) is registered as a singleton. I'm unsure how well a transient or scoped registration would work. 56 | 57 | .AddSingleton() 58 | 59 | .AddScoped() 60 | .AddScoped() 61 | 62 | .AddTransient() 63 | .AddTransient() 64 | ; 65 | } 66 | 67 | public static void GlobalAsaxApplicationStart( System.Web.HttpApplication httpApplication ) 68 | { 69 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(GlobalAsaxApplicationStart) + "() called: " + httpApplication.GetType().FullName ); 70 | } 71 | 72 | /// This method must be public for to recognize it. 73 | public static void OwinStartup( IAppBuilder appBuilder ) 74 | { 75 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(OwinStartup) + "() called." ); 76 | 77 | HubConfiguration hubConfig = new HubConfiguration() 78 | { 79 | EnableDetailedErrors = true 80 | }; 81 | 82 | #if USE_SCOPED_SIGNALR_RESOLVER 83 | IDependencyResolver dr = GlobalHost.DependencyResolver; 84 | if( dr is AspNetDependencyInjection.Internal.ScopedAndiSignalRDependencyResolver dr2 ) 85 | { 86 | dr2.ConfigureSignalR( appBuilder, path: "/signalr", hubConfiguration: hubConfig ); 87 | } 88 | else 89 | { 90 | throw new InvalidOperationException( nameof(AspNetDependencyInjection.Internal.UnscopedAndiSignalRDependencyResolver) + " is not set-up." ); 91 | } 92 | #else 93 | appBuilder.MapSignalR( path: "/signalr", configuration: hubConfig ); 94 | #endif 95 | } 96 | 97 | /// Invoked at the end of ASP.NET application start-up, after Global's Application_Start method runs. Dependency-injection re-configuration may be called here if you have services that depend on Global being initialized. 98 | internal static void PostStart() 99 | { 100 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PostStart) + "() called." ); 101 | } 102 | 103 | internal static void ApplicationShutdown() 104 | { 105 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(ApplicationShutdown) + "() called." ); 106 | 107 | _di.Dispose(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace SampleMvcWebApplication 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add( new HandleErrorAttribute() ); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace SampleMvcWebApplication 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Web.Mvc; 4 | 5 | using Microsoft.AspNet.SignalR; 6 | 7 | using SampleMvcWebApplication.SampleServices; 8 | 9 | namespace SampleMvcWebApplication.Controllers 10 | { 11 | public class HomeController : Controller 12 | { 13 | public const String Name = "Home"; 14 | 15 | private readonly ISampleSingletonService sgl; 16 | private readonly ISampleScopedService1 sc1; 17 | private readonly ISampleScopedService2 sc2; 18 | private readonly ISampleTransientService1 st1; 19 | private readonly ISampleTransientService2 st2; 20 | 21 | public HomeController( 22 | ISampleSingletonService sgl, 23 | ISampleScopedService1 sc1, 24 | ISampleScopedService2 sc2, 25 | ISampleTransientService1 st1, 26 | ISampleTransientService2 st2 27 | ) 28 | { 29 | this.sgl = sgl ?? throw new ArgumentNullException( nameof( sgl ) ); 30 | this.sc1 = sc1 ?? throw new ArgumentNullException( nameof( sc1 ) ); 31 | this.sc2 = sc2 ?? throw new ArgumentNullException( nameof( sc2 ) ); 32 | this.st1 = st1 ?? throw new ArgumentNullException( nameof( st1 ) ); 33 | this.st2 = st2 ?? throw new ArgumentNullException( nameof( st2 ) ); 34 | } 35 | 36 | public ActionResult Index() 37 | { 38 | #pragma warning disable IDE0059 // Unnecessary assignment of a value 39 | 40 | // Here's an example of getting a service without injecting it. It will still be scoped to the request (and so have the same lifetime as `sc1` and `sc2` above. 41 | IUserIdProvider userIdProvider = this.Resolver.GetService(); 42 | 43 | #pragma warning restore IDE0059 44 | 45 | return this.View(); 46 | } 47 | 48 | public ActionResult About() 49 | { 50 | this.ViewBag.Message = "Your application description page."; 51 | 52 | return this.View(); 53 | } 54 | 55 | public ActionResult Contact() 56 | { 57 | this.ViewBag.Message = "Your contact page."; 58 | 59 | return this.View(); 60 | } 61 | 62 | [HttpPost] 63 | public ActionResult SendMessage302( MvcSendMessageDto model ) 64 | { 65 | IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext(); 66 | hubContext.Clients.All.addChatMessageToPage( model.Name, model.Text ); 67 | 68 | return new RedirectResult( url: "/", permanent: false ); 69 | } 70 | 71 | [HttpPost] 72 | public ActionResult SendMessage204( MvcSendMessageDto model ) 73 | { 74 | IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext(); 75 | hubContext.Clients.All.addChatMessageToPage( model.Name, model.Text ); 76 | 77 | return new HttpStatusCodeResult( HttpStatusCode.NoContent ); 78 | } 79 | } 80 | 81 | public class MvcSendMessageDto 82 | { 83 | public String Name { get; set; } 84 | 85 | public String Text { get; set; } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Controllers/MessageHub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Web; 6 | using AspNetDependencyInjection; 7 | using Microsoft.AspNet.SignalR; 8 | 9 | namespace SampleMvcWebApplication.Controllers 10 | { 11 | public interface IMessagesHubClient 12 | { 13 | void addChatMessageToPage( String name, String text ); 14 | } 15 | 16 | // public interface IMessagesHubServer 17 | // { 18 | // void SendMessage( String name, String text ); 19 | // } 20 | 21 | public class MessagesHub : Hub//, IMessagesHubServer 22 | { 23 | private readonly IUserIdProvider userIdProvider; 24 | private readonly IWebConfiguration injectedConfig; 25 | 26 | public MessagesHub( IUserIdProvider userIdProvider, IWebConfiguration injected ) 27 | { 28 | this.userIdProvider = userIdProvider ?? throw new ArgumentNullException( nameof( userIdProvider ) ); 29 | this.injectedConfig = injected ?? throw new ArgumentNullException(nameof(injected)); 30 | 31 | System.Diagnostics.Debug.WriteLine( "MessagesHub created." ); 32 | } 33 | 34 | public override Task OnConnected() 35 | { 36 | return base.OnConnected(); 37 | } 38 | 39 | public void NewChatMessage( String name, String text ) 40 | { 41 | String newName = name + "(" + this.userIdProvider.GetUserId( this.Context.Request ) + ")"; 42 | String newText = text + this.injectedConfig.RequireAppSetting("messagesHubSuffix"); 43 | 44 | this.Clients.All.addChatMessageToPage( newName, newText ); 45 | } 46 | 47 | public void Started() 48 | { 49 | this.Clients.All.addChatMessageToPage( name: nameof(MessagesHub), text: this.Context.ConnectionId + " has started." ); 50 | } 51 | } 52 | } 53 | 54 | namespace SampleMvcWebApplication 55 | { 56 | public class SampleUserIdProvider : IUserIdProvider 57 | { 58 | const String cookieName = "ASP.NET_SessionId"; 59 | 60 | private readonly IWebConfiguration webConfig; 61 | 62 | public SampleUserIdProvider( IWebConfiguration injected ) 63 | { 64 | this.webConfig = injected ?? throw new ArgumentNullException( nameof( injected ) ); 65 | 66 | System.Diagnostics.Debug.WriteLine( nameof(SampleUserIdProvider) + " created." ); 67 | } 68 | 69 | public String GetUserId( IRequest request ) 70 | { 71 | if( request.Cookies.TryGetValue( cookieName, out Cookie value ) ) 72 | { 73 | return value.Value; 74 | } 75 | else 76 | { 77 | return "No Session cookie"; 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /SampleMvcWebApplication/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SampleMvcWebApplication.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | using System.Web.Routing; 9 | 10 | namespace SampleMvcWebApplication 11 | { 12 | public class MvcApplication : HttpApplication 13 | { 14 | protected void Application_Start() 15 | { 16 | SampleApplicationStart.GlobalAsaxApplicationStart( this ); 17 | 18 | AreaRegistration.RegisterAllAreas(); 19 | FilterConfig.RegisterGlobalFilters( GlobalFilters.Filters ); 20 | RouteConfig.RegisterRoutes( RouteTable.Routes ); 21 | } 22 | 23 | private static Int32 _sessionCounter = 0; 24 | 25 | protected void Session_Start( Object sender, EventArgs e ) 26 | { 27 | Debug.WriteLine( nameof(Session_Start) + " called." ); 28 | 29 | this.Session[ "counter" ] = Interlocked.Increment( ref _sessionCounter ); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle( "SampleMvcWebApplication" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "SampleMvcWebApplication" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2019" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible( false )] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid( "e2a1db60-14dd-4c1f-a7ec-6ecff9e6d64a" )] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion( "1.0.0.0" )] 35 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 36 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/SampleServices/ScopedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleMvcWebApplication.SampleServices 8 | { 9 | public interface ISampleScopedService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultScopedService1 : ISampleScopedService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultScopedService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleScopedService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultScopedService2 : ISampleScopedService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultScopedService2( ISampleSingletonService singletonService, ISampleTransientService1 transient1, ISampleTransientService2 transient2 ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonService = singletonService ?? throw new ArgumentNullException( nameof( singletonService ) ); 42 | this.Transient1 = transient1 ?? throw new ArgumentNullException( nameof( transient1 ) ); 43 | this.Transient2 = transient2 ?? throw new ArgumentNullException( nameof( transient2 ) ); 44 | } 45 | 46 | public Int32 InstanceId { get; } 47 | 48 | public ISampleSingletonService SingletonService { get; } 49 | public ISampleTransientService1 Transient1 { get; } 50 | public ISampleTransientService2 Transient2 { get; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/SampleServices/SingletonService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleMvcWebApplication.SampleServices 8 | { 9 | public interface ISampleSingletonService 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultSingletonService : ISampleSingletonService 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultSingletonService() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/SampleServices/TransientService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleMvcWebApplication.SampleServices 8 | { 9 | public interface ISampleTransientService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultTransientService1 : ISampleTransientService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultTransientService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleTransientService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultTransientService2 : ISampleTransientService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultTransientService2( ISampleSingletonService singleton ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonDependency = singleton; 42 | } 43 | 44 | public Int32 InstanceId { get; } 45 | 46 | public ISampleSingletonService SingletonDependency { get; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | 8 | 9 | 10 | 11 | 12 | @RenderSection("head", required: false) 13 | 14 | 15 | 34 |
35 | @RenderBody() 36 |
37 |
38 |

© @DateTime.Now.Year - My ASP.NET Application

39 |
40 |
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /SampleMvcWebApplication/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daiplusplus/AspNetDependencyInjection/f2774af584651932234c8447532eca90090669b3/SampleMvcWebApplication/favicon.ico -------------------------------------------------------------------------------- /SampleMvcWebApplication/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SampleWcfApplication/IService1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.ServiceModel; 6 | using System.ServiceModel.Web; 7 | using System.Text; 8 | 9 | using SampleWcfProject.SampleServices; 10 | 11 | namespace SampleWcfProject 12 | { 13 | // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. 14 | [ServiceContract] 15 | public interface IService1 16 | { 17 | 18 | [OperationContract] 19 | string GetData( int value ); 20 | 21 | [OperationContract] 22 | CompositeType GetDataUsingDataContract( CompositeType composite ); 23 | 24 | // TODO: Add your service operations here 25 | } 26 | 27 | 28 | // Use a data contract as illustrated in the sample below to add composite types to service operations. 29 | [DataContract] 30 | public class CompositeType 31 | { 32 | bool boolValue = true; 33 | string stringValue = "Hello "; 34 | 35 | [DataMember] 36 | public bool BoolValue 37 | { 38 | get { return this.boolValue; } 39 | set { this.boolValue = value; } 40 | } 41 | 42 | [DataMember] 43 | public string StringValue 44 | { 45 | get { return this.stringValue; } 46 | set { this.stringValue = value; } 47 | } 48 | } 49 | 50 | // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together. 51 | // NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging. 52 | public class Service1 : IService1 53 | { 54 | private readonly ISampleSingletonService sg1; 55 | private readonly ISampleTransientService2 st2; 56 | 57 | public Service1( ISampleSingletonService sg1, ISampleTransientService2 st2 ) 58 | { 59 | this.sg1 = sg1 ?? throw new ArgumentNullException( nameof( sg1 ) ); 60 | this.st2 = st2 ?? throw new ArgumentNullException( nameof( st2 ) ); 61 | } 62 | 63 | public String GetData( int value ) 64 | { 65 | return "Using Singleton service " + this.sg1.InstanceId + " and transient service " + this.st2.InstanceId; 66 | } 67 | 68 | public CompositeType GetDataUsingDataContract( CompositeType composite ) 69 | { 70 | if( composite == null ) 71 | { 72 | throw new ArgumentNullException( "composite" ); 73 | } 74 | 75 | if( composite.BoolValue ) 76 | { 77 | composite.StringValue += "Suffix"; 78 | } 79 | 80 | return composite; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /SampleWcfApplication/SampleServices/ScopedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWcfProject.SampleServices 8 | { 9 | public interface ISampleScopedService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultScopedService1 : ISampleScopedService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultScopedService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleScopedService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultScopedService2 : ISampleScopedService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultScopedService2( ISampleSingletonService singletonService, ISampleTransientService1 transient1, ISampleTransientService2 transient2 ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonService = singletonService ?? throw new ArgumentNullException( nameof( singletonService ) ); 42 | this.Transient1 = transient1 ?? throw new ArgumentNullException( nameof( transient1 ) ); 43 | this.Transient2 = transient2 ?? throw new ArgumentNullException( nameof( transient2 ) ); 44 | } 45 | 46 | public Int32 InstanceId { get; } 47 | 48 | public ISampleSingletonService SingletonService { get; } 49 | public ISampleTransientService1 Transient1 { get; } 50 | public ISampleTransientService2 Transient2 { get; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SampleWcfApplication/SampleServices/SingletonService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWcfProject.SampleServices 8 | { 9 | public interface ISampleSingletonService 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultSingletonService : ISampleSingletonService 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultSingletonService() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SampleWcfApplication/SampleServices/TransientService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWcfProject.SampleServices 8 | { 9 | public interface ISampleTransientService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultTransientService1 : ISampleTransientService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultTransientService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleTransientService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultTransientService2 : ISampleTransientService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultTransientService2( ISampleSingletonService singleton ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonDependency = singleton; 42 | } 43 | 44 | public Int32 InstanceId { get; } 45 | 46 | public ISampleSingletonService SingletonDependency { get; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SampleWcfApplication/Service1.svc: -------------------------------------------------------------------------------- 1 | <%@ ServiceHost Language="C#" Service="AspNetDependencyInjection.Wcf.Service1" Factory="AspNetDependencyInjection.Wcf.AndiWebServiceHostFactory" %> -------------------------------------------------------------------------------- /SampleWcfApplication/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /SampleWebApiService/App_Start/AppStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | using Owin; 6 | using Microsoft.Owin; 7 | using AspNetDependencyInjection; 8 | using WebActivatorEx; 9 | 10 | using SampleWebApiService; 11 | using SampleWebApiService.SampleServices; 12 | 13 | [assembly: PreApplicationStartMethod ( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PreStart ) )] 14 | [assembly: PostApplicationStartMethod( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PostStart ) )] 15 | [assembly: ApplicationShutdownMethod ( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.ApplicationShutdown ) )] 16 | 17 | [assembly: OwinStartup( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.OwinStartup ) )] 18 | 19 | namespace SampleWebApiService 20 | { 21 | /// Startup class for the AspNetDependencyInjection NuGet package. 22 | internal static class SampleApplicationStart 23 | { 24 | private static ApplicationDependencyInjection _di; 25 | 26 | /// Invoked when the ASP.NET application starts up, before Global's Application_Start method runs. Dependency-injection should be configured here. 27 | internal static void PreStart() 28 | { 29 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PreStart) + "() called." ); 30 | 31 | // If you are using ASP.NET Web Forms without any ASP.NET MVC functionality, remove the call to `.AddMvcDependencyResolver()`. 32 | // If you are using ASP.NET MVC, regardless of whether you're using ASP.NET Web Forms, use `.AddMvcDependencyResolver()`: 33 | 34 | _di = new ApplicationDependencyInjectionBuilder() 35 | .ConfigureServices( ConfigureServices ) 36 | .AddWebApiDependencyResolver() 37 | .Build(); 38 | } 39 | 40 | private static void ConfigureServices( IServiceCollection services ) 41 | { 42 | // TODO: Add any dependencies needed here 43 | _ = services 44 | // Useful services built-in to AspNetDependencyInjection: 45 | .AddDefaultHttpContextAccessor() // Adds `IHttpContextAccessor` 46 | .AddWebConfiguration() // Adds `IWebConfiguration` 47 | 48 | .AddSingleton() 49 | 50 | .AddScoped() 51 | .AddScoped() 52 | 53 | .AddTransient() 54 | .AddTransient() 55 | ; 56 | } 57 | 58 | public static void GlobalAsaxApplicationStart( System.Web.HttpApplication httpApplication ) 59 | { 60 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(GlobalAsaxApplicationStart) + "() called: " + httpApplication.GetType().FullName ); 61 | } 62 | 63 | /// This method must be public for to recognize it. 64 | public static void OwinStartup( IAppBuilder appBuilder ) 65 | { 66 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(OwinStartup) + "() called." ); 67 | } 68 | 69 | /// Invoked at the end of ASP.NET application start-up, after Global's Application_Start method runs. Dependency-injection re-configuration may be called here if you have services that depend on Global being initialized. 70 | internal static void PostStart() 71 | { 72 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PostStart) + "() called." ); 73 | } 74 | 75 | internal static void ApplicationShutdown() 76 | { 77 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(ApplicationShutdown) + "() called." ); 78 | 79 | _di.Dispose(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /SampleWebApiService/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Web.Http; 8 | using System.Text; 9 | 10 | using SampleWebApiService.SampleServices; 11 | 12 | namespace SampleWebApiService.Controllers 13 | { 14 | public class ValuesController : ApiController 15 | { 16 | private static readonly UTF8Encoding _utf8NoBom = new UTF8Encoding( encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false ); 17 | 18 | private readonly ISampleSingletonService sgl; 19 | private readonly ISampleScopedService1 sc1; 20 | private readonly ISampleScopedService2 sc2; 21 | private readonly ISampleTransientService1 st1; 22 | private readonly ISampleTransientService2 st2; 23 | 24 | public ValuesController( 25 | ISampleSingletonService sgl, 26 | ISampleScopedService1 sc1, 27 | ISampleScopedService2 sc2, 28 | ISampleTransientService1 st1, 29 | ISampleTransientService2 st2 30 | ) 31 | { 32 | this.sgl = sgl ?? throw new ArgumentNullException( nameof( sgl ) ); 33 | this.sc1 = sc1 ?? throw new ArgumentNullException( nameof( sc1 ) ); 34 | this.sc2 = sc2 ?? throw new ArgumentNullException( nameof( sc2 ) ); 35 | this.st1 = st1 ?? throw new ArgumentNullException( nameof( st1 ) ); 36 | this.st2 = st2 ?? throw new ArgumentNullException( nameof( st2 ) ); 37 | } 38 | 39 | [HttpGet] 40 | [Route("")] 41 | public HttpResponseMessage Get() 42 | { 43 | const String FMT = 44 | nameof(ISampleSingletonService) + " " + nameof(this.sgl) + ": Instance: {0}\r\n" + 45 | nameof(ISampleScopedService1) + " " + nameof(this.sc1) + ": Instance: {1}\r\n" + 46 | nameof(ISampleScopedService2) + " " + nameof(this.sc2) + ": Instance: {2}\r\n" + 47 | nameof(ISampleTransientService1) + " " + nameof(this.st1) + ": Instance: {3}\r\n" + 48 | nameof(ISampleTransientService2) + " " + nameof(this.st2) + ": Instance: {4}\r\n"; 49 | 50 | String text = String.Format( 51 | provider: CultureInfo.InvariantCulture, 52 | format : FMT, 53 | this.sgl.InstanceId, 54 | this.sc1.InstanceId, 55 | this.sc2.InstanceId, 56 | this.st1.InstanceId, 57 | this.st2.InstanceId 58 | ); 59 | 60 | return new HttpResponseMessage( HttpStatusCode.OK ) 61 | { 62 | Content = new StringContent( content: text, encoding: _utf8NoBom, mediaType: "text/plain" ) 63 | }; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SampleWebApiService/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SampleWebApiService.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /SampleWebApiService/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Routing; 7 | 8 | namespace SampleWebApiService 9 | { 10 | public class WebApiApplication : HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | GlobalConfiguration.Configure( ConfigureSelf ); 15 | } 16 | 17 | public static void ConfigureSelf( HttpConfiguration config ) 18 | { 19 | config.MapHttpAttributeRoutes(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SampleWebApiService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle( "SampleWebApiService" )] 9 | [assembly: AssemblyDescription( "" )] 10 | [assembly: AssemblyConfiguration( "" )] 11 | [assembly: AssemblyCompany( "" )] 12 | [assembly: AssemblyProduct( "SampleWebApiService" )] 13 | [assembly: AssemblyCopyright( "Copyright © 2021" )] 14 | [assembly: AssemblyTrademark( "" )] 15 | [assembly: AssemblyCulture( "" )] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible( false )] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid( "c46f52e0-5a60-4910-9370-a02f127a2f8d" )] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion( "1.0.0.0" )] 35 | [assembly: AssemblyFileVersion( "1.0.0.0" )] 36 | -------------------------------------------------------------------------------- /SampleWebApiService/SampleServices/ScopedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWebApiService.SampleServices 8 | { 9 | public interface ISampleScopedService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultScopedService1 : ISampleScopedService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultScopedService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleScopedService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultScopedService2 : ISampleScopedService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultScopedService2( ISampleSingletonService singletonService, ISampleTransientService1 transient1, ISampleTransientService2 transient2 ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonService = singletonService ?? throw new ArgumentNullException( nameof( singletonService ) ); 42 | this.Transient1 = transient1 ?? throw new ArgumentNullException( nameof( transient1 ) ); 43 | this.Transient2 = transient2 ?? throw new ArgumentNullException( nameof( transient2 ) ); 44 | } 45 | 46 | public Int32 InstanceId { get; } 47 | 48 | public ISampleSingletonService SingletonService { get; } 49 | public ISampleTransientService1 Transient1 { get; } 50 | public ISampleTransientService2 Transient2 { get; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SampleWebApiService/SampleServices/SingletonService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWebApiService.SampleServices 8 | { 9 | public interface ISampleSingletonService 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultSingletonService : ISampleSingletonService 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultSingletonService() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SampleWebApiService/SampleServices/TransientService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Web; 6 | 7 | namespace SampleWebApiService.SampleServices 8 | { 9 | public interface ISampleTransientService1 10 | { 11 | Int32 InstanceId { get; } 12 | } 13 | 14 | public class DefaultTransientService1 : ISampleTransientService1 15 | { 16 | private static Int32 _idSeed = 0; 17 | 18 | public DefaultTransientService1() 19 | { 20 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 21 | } 22 | 23 | public Int32 InstanceId { get; } 24 | } 25 | 26 | // 27 | 28 | public interface ISampleTransientService2 29 | { 30 | Int32 InstanceId { get; } 31 | } 32 | 33 | public class DefaultTransientService2 : ISampleTransientService2 34 | { 35 | private static Int32 _idSeed = 0; 36 | 37 | public DefaultTransientService2( ISampleSingletonService singleton ) 38 | { 39 | this.InstanceId = Interlocked.Increment( ref _idSeed ); 40 | 41 | this.SingletonDependency = singleton; 42 | } 43 | 44 | public Int32 InstanceId { get; } 45 | 46 | public ISampleSingletonService SingletonDependency { get; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SampleWebApiService/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /SampleWebApiService/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /SampleWebApplication/App_Start/SampleApplicationStart.cs: -------------------------------------------------------------------------------- 1 | 2 | using AspNetDependencyInjection; 3 | using AspNetDependencyInjection.Configuration; 4 | using AspNetDependencyInjection.Services; 5 | 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | using SampleWebApplication; 9 | 10 | using WebActivatorEx; 11 | 12 | [assembly: PreApplicationStartMethod( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PreStart ) )] 13 | [assembly: PostApplicationStartMethod( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.PostStart ) )] 14 | [assembly: ApplicationShutdownMethod( typeof( SampleApplicationStart ), methodName: nameof( SampleApplicationStart.ApplicationShutdown ) )] 15 | 16 | namespace SampleWebApplication 17 | { 18 | /// Startup class for the AspNetDependencyInjection NuGet package. 19 | internal static class SampleApplicationStart 20 | { 21 | private static ApplicationDependencyInjection _di; // This is disposed in `ApplicationShutdown()`. 22 | 23 | /// Invoked when the ASP.NET application starts up, before Global's Application_Start method runs. Dependency-injection should be configured here. 24 | internal static void PreStart() 25 | { 26 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PreStart) + "() called." ); 27 | 28 | // If you are using ASP.NET MVC, regardless of whether you're using ASP.NET Web Forms or the ASPX View Engine, use `.AddMvcDependencyResolver()` (you will need to reference the `AspNetDependencyInjection.Mvc` package/assembly first). 29 | 30 | _di = new ApplicationDependencyInjectionBuilder() 31 | .ConfigureServices( ConfigureServices ) 32 | .Build(); 33 | } 34 | 35 | private static void ConfigureServices( IServiceCollection services ) 36 | { 37 | // TODO: Add any dependencies needed here 38 | _ = services 39 | .AddDefaultHttpContextAccessor() 40 | .AddScoped() 41 | .AddTransient() 42 | .AddScoped() 43 | .AddScoped() 44 | .AddSingleton(); 45 | } 46 | 47 | /// Invoked at the end of ASP.NET application start-up, after Global's Application_Start method runs. Dependency-injection re-configuration may be called here if you have services that depend on Global being initialized. 48 | internal static void PostStart() 49 | { 50 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PostStart) + "() called." ); 51 | } 52 | 53 | internal static void ApplicationShutdown() 54 | { 55 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(ApplicationShutdown) + "() called." ); 56 | 57 | _di.Dispose(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SampleWebApplication/App_Start/SampleApplicationStart.template.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | using AspNetDependencyInjection; 5 | 6 | [assembly: WebActivatorEx.PreApplicationStartMethod ( typeof($rootnamespace$.ApplicationStart), nameof($rootnamespace$.ApplicationStart.PreStart ) )] 7 | [assembly: WebActivatorEx.PostApplicationStartMethod( typeof($rootnamespace$.ApplicationStart), nameof($rootnamespace$.ApplicationStart.PostStart) )] 8 | 9 | namespace $rootnamespace$ 10 | { 11 | /// Startup class for your application. Configures dependency-injection. 12 | internal static class ApplicationStart 13 | { 14 | private static ApplicationDependencyInjection _di; 15 | 16 | /// Invoked when the ASP.NET application starts up, before Global's Application_Start method runs. Dependency-injection should be configured here. 17 | internal static void PreStart() 18 | { 19 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PreStart) + "() called." ); 20 | 21 | _di = ApplicationDependencyInjection.Configure( ConfigureServices ); 22 | } 23 | 24 | private static void ConfigureServices( IServiceCollection services ) 25 | { 26 | // TODO: Add any dependencies needed here 27 | services 28 | .AddDefaultHttpContextAccessor() 29 | .AddScoped() 30 | .AddTransient() 31 | .AddScoped() 32 | .AddScoped() 33 | .AddSingleton(); 34 | } 35 | 36 | /// Invoked at the end of ASP.NET application start-up, after Global's Application_Start method runs. Dependency-injection re-configuration may be called here if you have services that depend on Global being initialized. 37 | internal static void PostStart() 38 | { 39 | System.Diagnostics.Debug.WriteLine( nameof(SampleApplicationStart) + "." + nameof(PostStart) + "() called." ); 40 | 41 | _di.Reconfigure( ReconfigureServices ); 42 | } 43 | 44 | private static void ReconfigureServices( IServiceCollection services ) 45 | { 46 | 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /SampleWebApplication/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SampleWebApplication.DefaultPage" %> 2 | 3 | <%@ Register src="InjectedControl.ascx" tagName="InjectedControl" tagPrefix="UC" %> 4 | <%@ Register src="SampleExcludedExternalControl.ascx" tagName="SampleExcludedExternalControl" tagPrefix="UC" %> 5 | <%@ Register src="SampleIncludedExternalControl.ascx" tagName="SampleIncludedExternalControl" tagPrefix="UC" %> 6 | 7 | 8 | 9 | 10 | 11 |

Welcome to Injected ASP.NET WebForms using AspNetDependencyInjection!

12 |

13 | To learn more about AspNetDependencyInjection, visit https://github.com/Jehoel/AspNetDependencyInjection. 14 |

15 | 16 |
17 | 18 |
19 | Request-lifetime service 20 | 21 |

<%: this.InjectedService3.ToString() %>

22 | 23 |
24 | 25 |
26 | 27 |
28 | Injected Page 29 | 30 |

Service 1: <%: this.InjectedService1.SayHello() %>

31 |

Service 2: <%: this.InjectedService2.SayHello() %>

32 |
33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 |
47 | 48 |
49 | Dynamically generated control; resolved manually 50 | 51 | 52 |
53 | 54 |
55 | 56 |
57 | -------------------------------------------------------------------------------- /SampleWebApplication/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.UI; 3 | 4 | namespace SampleWebApplication 5 | { 6 | /// 7 | /// Sample page demonstrating injection at the page level. 8 | /// 9 | public partial class DefaultPage : Page 10 | { 11 | private readonly IExampleRequestLifelongService exampleService; 12 | private readonly Service4 service4; 13 | 14 | public DefaultPage( Service1 service1, Service2 service2, IExampleRequestLifelongService exampleService, Service4 service4 ) 15 | { 16 | this.InjectedService1 = service1; 17 | this.InjectedService2 = service2; 18 | this.exampleService = exampleService ?? throw new ArgumentNullException(nameof(exampleService)); 19 | this.service4 = service4 ?? throw new ArgumentNullException(nameof(service4)); 20 | } 21 | 22 | protected override void OnInit( EventArgs e ) 23 | { 24 | if( !this.IsPostBack ) 25 | { 26 | this.AddControls(); 27 | } 28 | 29 | base.OnInit( e ); 30 | } 31 | 32 | protected void Page_Load( object sender, EventArgs e ) 33 | { 34 | this.InjectedService3.DoSomething(); 35 | this.service4.DoSomething(); 36 | } 37 | 38 | #region Helpers 39 | 40 | /// 41 | /// Dynamically adds a new User Control to the page, resolving the 42 | /// dependencies manually. 43 | /// 44 | private void AddControls() 45 | { 46 | InjectedControl newControl = this.LoadControl("InjectedControl.ascx") as InjectedControl; 47 | this.DynamicInjectedControl.Controls.Add( newControl ); 48 | } 49 | 50 | #endregion 51 | 52 | #region Dependencies 53 | 54 | /// Gets/sets the dependency (injected). 55 | public Service1 InjectedService1 { get; set; } 56 | 57 | /// Gets/sets the dependency (injected). 58 | public Service2 InjectedService2 { get; set; } 59 | 60 | public IExampleRequestLifelongService InjectedService3 => this.exampleService; 61 | 62 | #endregion 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /SampleWebApplication/Default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace SampleWebApplication { 11 | 12 | 13 | public partial class DefaultPage { 14 | 15 | /// 16 | /// InjectedUC control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::SampleWebApplication.InjectedControl InjectedUC; 23 | 24 | /// 25 | /// SampleExcludedExternalControl control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::ExcludedNamespace.SampleWebApplication.SampleExcludedExternalControl SampleExcludedExternalControl; 32 | 33 | /// 34 | /// SampleIncludedExternalControl control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::IncludedNamespace.SampleWebApplication.SampleIncludedExternalControl SampleIncludedExternalControl; 41 | 42 | /// 43 | /// DynamicInjectedControl control. 44 | /// 45 | /// 46 | /// Auto-generated field. 47 | /// To modify move field declaration from designer file to code-behind file. 48 | /// 49 | protected global::System.Web.UI.WebControls.PlaceHolder DynamicInjectedControl; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SampleWebApplication/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SampleWebApplication.SampleWebApplicationHttpApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /SampleWebApplication/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Security; 6 | using System.Web.SessionState; 7 | 8 | namespace SampleWebApplication 9 | { 10 | public class SampleWebApplicationHttpApplication : HttpApplication 11 | { 12 | private static Int32 _idSeed; 13 | 14 | private readonly Int32 id = System.Threading.Interlocked.Increment( ref _idSeed ); 15 | 16 | public SampleWebApplicationHttpApplication() 17 | { 18 | 19 | } 20 | 21 | void Application_Start(object sender, EventArgs e) 22 | { 23 | // Code that runs on application startup 24 | 25 | } 26 | 27 | void Application_End(object sender, EventArgs e) 28 | { 29 | // Code that runs on application shutdown 30 | 31 | } 32 | 33 | void Application_Error(object sender, EventArgs e) 34 | { 35 | // Code that runs when an unhandled error occurs 36 | 37 | } 38 | 39 | void Session_Start(object sender, EventArgs e) 40 | { 41 | // Code that runs when a new session is started 42 | 43 | } 44 | 45 | void Session_End(object sender, EventArgs e) 46 | { 47 | // Code that runs when a session ends. 48 | // Note: The Session_End event is raised only when the sessionstate mode 49 | // is set to InProc in the Web.config file. If session mode is set to StateServer 50 | // or SQLServer, the event is not raised. 51 | 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SampleWebApplication/InjectedControl.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="InjectedControl.ascx.cs" Inherits="SampleWebApplication.InjectedControl" %> 2 | 3 | 4 |
5 | Injected User Control 6 | 7 |

Service 1 = <%: InjectedService1.SayHello() %>

8 |

Service 2 = <%: InjectedService2.SayHello() %>

9 |
-------------------------------------------------------------------------------- /SampleWebApplication/InjectedControl.ascx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.UI; 3 | 4 | namespace SampleWebApplication 5 | { 6 | /// Sample User Control demonstrating constructor service injection into UserControls. 7 | public partial class InjectedControl : UserControl 8 | { 9 | /// NOTE: For reasons not yet fully understood, when using constructor-injected services in UserControls, the UserControl must be a public class (not abstract) and must have a public (not protected) constructor. 10 | public InjectedControl( Service1 service1, Service2 service2 ) 11 | { 12 | this.InjectedService1 = service1 ?? throw new ArgumentNullException(nameof(service1)); 13 | this.InjectedService2 = service2 ?? throw new ArgumentNullException(nameof(service2)); 14 | } 15 | 16 | /// Gets the dependency (injected). 17 | public Service1 InjectedService1 { get; } 18 | 19 | /// Gets the dependency (injected). 20 | public Service2 InjectedService2 { get; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SampleWebApplication/InjectedControl.ascx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace SampleWebApplication 11 | { 12 | 13 | 14 | public partial class InjectedControl 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SampleWebApplication/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SampleWebApplication")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SampleWebApplication")] 13 | [assembly: AssemblyCopyright("Copyright © 2013-2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("dc99a883-f2f8-4c4b-ac39-7bee5e8cdd37")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("2.0.*")] 35 | //[assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SampleWebApplication/SampleExcludedExternalControl.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SampleExcludedExternalControl.ascx.cs" Inherits="ExcludedNamespace.SampleWebApplication.SampleExcludedExternalControl" %> 2 | 3 |
4 | External User Control - Excluded (Services should be null) 5 | 6 |

Service1 is

7 |

Service1 is

8 |
-------------------------------------------------------------------------------- /SampleWebApplication/SampleExcludedExternalControl.ascx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using SampleWebApplication; 4 | 5 | namespace ExcludedNamespace.SampleWebApplication 6 | { 7 | /// This control's dependencies should be excluded from DI because it is in the "Foo." namespace which is excluded as per the <ignoreNamspaces> configuration in web.config. 8 | public partial class SampleExcludedExternalControl : System.Web.UI.UserControl 9 | { 10 | public SampleExcludedExternalControl( Service1 service1, Service2 service2 ) 11 | { 12 | this.Service1 = service1 ?? throw new ArgumentNullException(nameof(service1)); 13 | this.Service2 = service2 ?? throw new ArgumentNullException(nameof(service2)); 14 | } 15 | 16 | protected void Page_Load(object sender, EventArgs e) 17 | { 18 | this.serviceOne.Text = this.Service1 == null ? "null" : "not null"; 19 | this.serviceTwo.Text = this.Service2 == null ? "null" : "not null"; 20 | } 21 | 22 | public Service1 Service1 { get; set; } 23 | 24 | public Service2 Service2 { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /SampleWebApplication/SampleExcludedExternalControl.ascx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace ExcludedNamespace.SampleWebApplication { 11 | 12 | 13 | public partial class SampleExcludedExternalControl { 14 | 15 | /// 16 | /// serviceOne control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.Literal serviceOne; 23 | 24 | /// 25 | /// serviceTwo control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Literal serviceTwo; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SampleWebApplication/SampleIncludedExternalControl.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SampleIncludedExternalControl.ascx.cs" Inherits="IncludedNamespace.SampleWebApplication.SampleIncludedExternalControl" %> 2 | 3 |
4 | External User Control - Included (Services should not be null) 5 | 6 |

Service1 is

7 |

Service1 is

8 |
-------------------------------------------------------------------------------- /SampleWebApplication/SampleIncludedExternalControl.ascx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using SampleWebApplication; 4 | 5 | namespace IncludedNamespace.SampleWebApplication 6 | { 7 | public partial class SampleIncludedExternalControl : System.Web.UI.UserControl 8 | { 9 | public SampleIncludedExternalControl( Service1 service1, Service2 service2 ) 10 | { 11 | this.Service1 = service1 ?? throw new ArgumentNullException(nameof(service1)); 12 | this.Service2 = service2 ?? throw new ArgumentNullException(nameof(service2)); 13 | } 14 | 15 | protected void Page_Load(object sender, EventArgs e) 16 | { 17 | this.serviceOne.Text = this.Service1 == null ? "null" : "not null"; 18 | this.serviceTwo.Text = this.Service2 == null ? "null" : "not null"; 19 | } 20 | 21 | public Service1 Service1 { get; set; } 22 | 23 | public Service2 Service2 { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /SampleWebApplication/SampleIncludedExternalControl.ascx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace IncludedNamespace.SampleWebApplication { 11 | 12 | 13 | public partial class SampleIncludedExternalControl { 14 | 15 | /// 16 | /// serviceOne control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.Literal serviceOne; 23 | 24 | /// 25 | /// serviceTwo control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Literal serviceTwo; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SampleWebApplication/Service1.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace SampleWebApplication 3 | { 4 | /// Sample service with no dependencies. 5 | public class Service1 6 | { 7 | /// Offers a greeting. 8 | /// A greeting from the service. 9 | public string SayHello() 10 | { 11 | return string.Format( "Hello from Service 1 [Object ID = {0}]", this.GetHashCode() ); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /SampleWebApplication/Service2.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace SampleWebApplication 3 | { 4 | /// 5 | /// Sample service that has a dependency on another service. 6 | /// 7 | /// This is using the preferred injection technique (constructor). 8 | public class Service2 9 | { 10 | /// Backing field for dependent service. 11 | private Service1 _service1; 12 | 13 | /// 14 | /// Initializes a new instance of the service with an injected 15 | /// dependency. 16 | /// 17 | /// Injected dependency, 18 | public Service2( Service1 svc1 ) 19 | { 20 | this._service1 = svc1; 21 | } 22 | 23 | /// 24 | /// Offers a greeting. 25 | /// 26 | /// 27 | /// A greeting from this service combined with the greeting from 28 | /// the dependent service. 29 | /// 30 | public string SayHello() 31 | { 32 | return string.Format( "{0} (Called from Service2 [Object ID = {1}])", this._service1.SayHello(), this.GetHashCode() ); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /SampleWebApplication/Service3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | 9 | namespace SampleWebApplication 10 | { 11 | public interface IExampleRequestLifelongService : IDisposable 12 | { 13 | void DoSomething(); 14 | 15 | Int32 ConstructorCallCount { get; } 16 | 17 | Int32 InstanceNumber { get; } 18 | 19 | Int32 InstanceDoSomethingCallCount { get; } 20 | 21 | Int32 SharedDoSomethingCallCount { get; } 22 | } 23 | 24 | public sealed class ExampleRequestLifelongService : IExampleRequestLifelongService 25 | { 26 | private static Int32 _ctorCallCount; 27 | private static Int32 _sharedCallCount; 28 | private static Int32 _disposedCount; 29 | 30 | private readonly Int32 instanceNumber; 31 | private Int32 callCount; 32 | 33 | private Boolean isDisposed; 34 | 35 | public Int32 ConstructorCallCount => _ctorCallCount; 36 | 37 | public Int32 InstanceDoSomethingCallCount => this.callCount; 38 | 39 | public Int32 SharedDoSomethingCallCount => _sharedCallCount; 40 | 41 | public Int32 InstanceNumber => this.instanceNumber; 42 | 43 | public Int32 DisposedCount => _disposedCount; 44 | 45 | public ExampleRequestLifelongService() 46 | { 47 | this.instanceNumber = Interlocked.Increment( ref _ctorCallCount ); 48 | 49 | Task verifyTask = Task.Run( this.VerifyIsDisposedAsync ); 50 | } 51 | 52 | public void DoSomething() 53 | { 54 | this.callCount++; 55 | 56 | Interlocked.Increment( ref _sharedCallCount ); 57 | } 58 | 59 | [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations" )] 60 | public void Dispose() 61 | { 62 | if( this.isDisposed ) 63 | { 64 | // This exception is only thrown for demonstration purposes. Never throw an exception from a Dispose method in production code! 65 | throw new InvalidOperationException( "This instance is already disposed." ); 66 | } 67 | else 68 | { 69 | this.isDisposed = true; 70 | 71 | Interlocked.Increment( ref _disposedCount ); 72 | } 73 | } 74 | 75 | private async Task VerifyIsDisposedAsync() 76 | { 77 | await Task.Delay( millisecondsDelay: 10 * 1000 ); // Wait 10 seconds after the instance has been constructed (assuming no HTTP request takes 10 seconds to run). 78 | 79 | if( !this.isDisposed ) 80 | { 81 | throw new InvalidOperationException( "This instance was not disposed after its parent HTTP request had (presumably) completed." ); 82 | } 83 | } 84 | 85 | public override String ToString() 86 | { 87 | const String fmt = "Static: ( Ctor calls: {0}, DoSomething calls: {1}, Disposed count: {2} ), Instance: ( Instance number: {3}, DoSomething calls: {4} )"; 88 | return String.Format( CultureInfo.CurrentCulture, fmt, this.ConstructorCallCount, this.SharedDoSomethingCallCount, this.DisposedCount, this.InstanceNumber, this.InstanceDoSomethingCallCount ); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /SampleWebApplication/Service4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using AspNetDependencyInjection; 6 | 7 | namespace SampleWebApplication 8 | { 9 | public class Service4 10 | { 11 | private readonly IExampleRequestLifelongService service; 12 | private readonly IHttpContextAccessor httpContextAccessor; 13 | 14 | public Service4( IExampleRequestLifelongService service3, IHttpContextAccessor httpContextAccessor ) 15 | { 16 | this.service = service3 ?? throw new ArgumentNullException(nameof(service3)); 17 | this.httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); 18 | } 19 | 20 | public void DoSomething() 21 | { 22 | this.httpContextAccessor.HttpContext.Response.AddHeader( "X-HttpContextAccessor-Works", "1" ); 23 | 24 | this.service.DoSomething(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /SampleWebApplication/SingletonService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace SampleWebApplication 7 | { 8 | public class SingletonService 9 | { 10 | private static Int32 _idSeed; 11 | 12 | public SingletonService() 13 | { 14 | this.Id = System.Threading.Interlocked.Increment( ref _idSeed ); 15 | } 16 | 17 | public Int32 Id { get; } 18 | } 19 | } -------------------------------------------------------------------------------- /SampleWebApplication/Site.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SampleWebApplication.SiteMaster" %> 2 | 3 | 4 | 5 | 6 | AspNetDependencyInjection 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |

AspNetDependencyInjection

18 |
19 | 27 |
28 |
29 | 30 | 31 |
32 | Injected Master Page 33 | 34 |

Service 1: <%: InjectedService1.SayHello() %>

35 |

Service 2: <%: InjectedService2.SayHello() %>

36 |
37 |
38 |
39 |
40 |
41 | 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /SampleWebApplication/Site.Master.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace SampleWebApplication { 11 | 12 | 13 | public partial class SiteMaster { 14 | 15 | /// 16 | /// HeadContent control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.ContentPlaceHolder HeadContent; 23 | 24 | /// 25 | /// NavigationMenu control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.Menu NavigationMenu; 32 | 33 | /// 34 | /// MainContent control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SampleWebApplication/Site.master.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web.UI; 3 | 4 | namespace SampleWebApplication 5 | { 6 | /// Sample master Sample page demonstrating constructor service injection into MasterPages. 7 | public partial class SiteMaster : MasterPage 8 | { 9 | public SiteMaster( Service1 service1, Service2 service2 ) 10 | { 11 | this.InjectedService1 = service1 ?? throw new ArgumentNullException(nameof(service1)); 12 | this.InjectedService2 = service2 ?? throw new ArgumentNullException(nameof(service2)); 13 | } 14 | 15 | /// Gets the dependency (injected). 16 | public Service1 InjectedService1 { get; } 17 | 18 | /// Gets the dependency (injected). 19 | public Service2 InjectedService2 { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SampleWebApplication/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /SampleWebApplication/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/AppCode/DevHttpClientHandler.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Net.Http 3 | Imports System.Threading 4 | Imports System.Threading.Tasks 5 | 6 | Public Class DevHttpClientHandler 7 | Inherits HttpClientHandler 8 | 9 | 10 | Public Sub New() 11 | 12 | End Sub 13 | 14 | Protected Overrides Function SendAsync(request As HttpRequestMessage, cancellationToken As CancellationToken) As Task(Of HttpResponseMessage) 15 | If cancellationToken.IsCancellationRequested Then cancellationToken.ThrowIfCancellationRequested() 16 | Dim response = New HttpResponseMessage(Net.HttpStatusCode.OK) With { 17 | .Content = New StringContent("Greetings, from Developer land!") 18 | } 19 | Return Task.FromResult(response) 20 | End Function 21 | End Class 22 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/App_Start/SampleApplicationStart.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Net.Http 3 | Imports System.Diagnostics 4 | Imports System.Runtime 5 | 6 | Imports Microsoft.Extensions.DependencyInjection 7 | 8 | Imports AspNetDependencyInjection 9 | Imports WebActivatorEx 10 | 11 | 12 | 13 | 14 | 15 | ''' Startup class for the AspNetDependencyInjection NuGet package. 16 | Friend Module SampleApplicationStartVB 17 | 18 | Private _di As ApplicationDependencyInjection 19 | ''' Invoked when the ASP.NET application starts up, before Global's Application_Start method runs. Dependency-injection should be configured here. 20 | Public Sub PreStart() 21 | Debug.WriteLine(NameOf(SampleApplicationStartVB) & "." & NameOf(PreStart) & "() called.") 22 | 23 | _di = New ApplicationDependencyInjectionBuilder(). 24 | ConfigureServices(AddressOf ConfigureServices). 25 | Build() 26 | End Sub 27 | 28 | Private Sub ConfigureServices(services As IServiceCollection) 29 | ' TODO: Add any dependencies needed here 30 | services = services.AddDefaultHttpContextAccessor() 31 | 32 | Dim devMode As Boolean = True 33 | Dim apiBase As String = "https://github.com/Jehoel/AspNetDependencyInjection" 34 | 35 | services.AddHttpClient("exampleFactory", Sub(c As HttpClient) 36 | c.BaseAddress = New Uri(apiBase) 37 | 'c.DefaultRequestHeaders.Authorization = New System.Net.Http.Headers.AuthenticationHeaderValue("Basic", $"") 38 | End Sub). 39 | ConfigurePrimaryHttpMessageHandler(Function(provider) As System.Net.Http.HttpMessageHandler 40 | If (Not devMode) Then Return New HttpClientHandler() 41 | 42 | Return CType(New DevHttpClientHandler, HttpMessageHandler) 43 | End Function) 44 | End Sub 45 | 46 | 47 | ''' Invoked at the end of ASP.NET application start-up, after Global's Application_Start method runs. Dependency-injection re-configuration may be called here if you have services that depend on Global being initialized. 48 | Public Sub PostStart() 49 | Debug.WriteLine(NameOf(SampleApplicationStartVB) & "." & NameOf(PostStart) & "() called.") 50 | End Sub 51 | 52 | Public Sub ApplicationShutdown() 53 | Debug.WriteLine(NameOf(SampleApplicationStartVB) & "." & NameOf(ApplicationShutdown) & "() called.") 54 | End Sub 55 | End Module 56 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Title="Home Page" Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.vb" Inherits="SampleWebApplicationVB.DefaultPage" %> 2 | 3 | 4 | 5 | 6 | 7 |

Welcome to Injected ASP.NET WebForms

8 | 9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Default.aspx.designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' 5 | ' Changes to this file may cause incorrect behavior and will be lost if 6 | ' the code is regenerated. 7 | ' 8 | '------------------------------------------------------------------------------ 9 | 10 | Option Strict On 11 | Option Explicit On 12 | 13 | 14 | Partial Public Class DefaultPage 15 | 16 | ''' 17 | '''ltMessages control. 18 | ''' 19 | ''' 20 | '''Auto-generated field. 21 | '''To modify move field declaration from designer file to code-behind file. 22 | ''' 23 | Protected WithEvents ltMessages As Global.System.Web.UI.WebControls.Literal 24 | End Class 25 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Default.aspx.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Net.Http 3 | Imports System.Web.UI 4 | 5 | 6 | ''' 7 | ''' Sample page demonstrating injection at the page level. 8 | ''' <'summary> 9 | Partial Public Class DefaultPage 10 | Inherits Page 11 | 12 | Private ReadOnly httpClientFactory As IHttpClientFactory 13 | 14 | Public Sub New(httpClientFactory As IHttpClientFactory) 15 | Me.httpClientFactory = httpClientFactory 16 | End Sub 17 | 18 | Protected Overrides Sub OnInit(e As EventArgs) 19 | If (Not Me.IsPostBack) Then 20 | AddControls() 21 | End If 22 | 23 | MyBase.OnInit(e) 24 | End Sub 25 | 26 | Protected Sub Page_Load(sender As Object, e As EventArgs) 27 | Dim client = HttpClientFactory.CreateClient("exampleFactory") 28 | Me.ltMessages.Text = client.BaseAddress.ToString() 29 | End Sub 30 | 31 | ''' 32 | ''' Dynamically add a New User Control to the page, resolving the 33 | ''' dependencies manually. 34 | ''' <'summary> 35 | Private Sub AddControls() 36 | 37 | End Sub 38 | 39 | 40 | End Class 41 | 42 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.vb" Inherits="SampleWebApplicationVB.SampleHttpApplication" Language="VB" %> 2 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Global.asax.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Web 5 | Imports System.Web.Security 6 | Imports System.Web.SessionState 7 | 8 | 9 | Public Class SampleHttpApplication 10 | Inherits HttpApplication 11 | 12 | Private Shared _idSeed As Int32 13 | 14 | Private ReadOnly id As Int32 = System.Threading.Interlocked.Increment(_idSeed) 15 | 16 | Public Sub New() 17 | End Sub 18 | 19 | Sub Application_Start(sender As Object, e As EventArgs) 20 | '' Code that runs on application startup 21 | End Sub 22 | 23 | Sub Application_End(sender As Object, e As EventArgs) 24 | '' Code that runs on application shutdown 25 | End Sub 26 | 27 | Sub Application_Error(sender As Object, e As EventArgs) 28 | '' Code that runs when an unhandled error occurs 29 | End Sub 30 | 31 | Sub Session_Start(sender As Object, e As EventArgs) 32 | '' Code that runs when a new session is started 33 | End Sub 34 | 35 | Sub Session_End(sender As Object, e As EventArgs) 36 | '' Code that runs when a session ends. 37 | '' Note: The Session_End event is raised only when the sessionstate mode 38 | '' is set to InProc in the Web.config file. If session mode is set to StateServer 39 | '' or SQLServer, the event is not raised. 40 | End Sub 41 | 42 | End Class 43 | 44 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Properties/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | imports System.Reflection 2 | imports System.Runtime.CompilerServices 3 | imports System.Runtime.InteropServices 4 | 5 | '' General Information about an assembly is controlled through the following 6 | '' set of attributes. Change these attribute values to modify the information 7 | '' associated with an assembly. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | '' Setting ComVisible to false makes the types in this assembly not visible 18 | '' to COM components. If you need to access a type in this assembly from 19 | '' COM, set the ComVisible attribute to true on that type. 20 | 21 | 22 | '' The following GUID is for the ID of the typelib if this project is exposed to COM 23 | 24 | 25 | '' Version information for an assembly consists of the following four values: 26 | '' 27 | '' Major Version 28 | '' Minor Version 29 | '' Build Number 30 | '' Revision 31 | '' 32 | '' You can specify all the values or you can default the Revision and Build Numbers 33 | '' by using the '*' as shown below: 34 | 35 | '' 36 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Site.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="VB" AutoEventWireup="true" CodeBehind="Site.master.vb" Inherits="SampleWebApplicationVB.SiteMaster" %> 2 | 3 | 4 | 5 | 6 | WebForms 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |

WebForms

18 |
19 | 26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 | 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Site.master.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Web.UI 3 | 4 | ''' 5 | ''' Sample master Sample page demonstrating injection at the page level. 6 | ''' 7 | Partial Public Class SiteMaster 8 | Inherits MasterPage 9 | 10 | 11 | Protected Sub Page_Load(sender As Object, e As EventArgs) 12 | 13 | End Sub 14 | 15 | 16 | End Class 17 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /SampleWebApplicationVB/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /packages/Microsoft.Web.Infrastructure.1.0.0.0/Microsoft.Web.Infrastructure.1.0.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daiplusplus/AspNetDependencyInjection/f2774af584651932234c8447532eca90090669b3/packages/Microsoft.Web.Infrastructure.1.0.0.0/Microsoft.Web.Infrastructure.1.0.0.0.nupkg -------------------------------------------------------------------------------- /packages/Microsoft.Web.Infrastructure.1.0.0.0/lib/net40/Microsoft.Web.Infrastructure.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daiplusplus/AspNetDependencyInjection/f2774af584651932234c8447532eca90090669b3/packages/Microsoft.Web.Infrastructure.1.0.0.0/lib/net40/Microsoft.Web.Infrastructure.dll -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | --------------------------------------------------------------------------------