diff --git a/src/UnityAdapter/ContainerServiceProvider.cs b/src/UnityAdapter/ContainerServiceProvider.cs index 63cdeb6..ca820ba 100644 --- a/src/UnityAdapter/ContainerServiceProvider.cs +++ b/src/UnityAdapter/ContainerServiceProvider.cs @@ -1,4 +1,5 @@ - +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity { @@ -6,6 +7,7 @@ namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity using global::Unity.Exceptions; using System; using System.Collections.Concurrent; + using System.Collections.Generic; using System.Reflection; using System.Web.Hosting; @@ -76,7 +78,7 @@ namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity return result; } - public IUnityContainer Container { get; } = new UnityContainer(); + public IUnityContainer Container { get; internal set; } = new UnityContainer(); public void Stop(bool immediate) { @@ -85,6 +87,16 @@ namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity Container.Dispose(); } + internal IServiceProvider NextServiceProvider + { + get { return _next; } + } + + internal IDictionary TypeCannotResolveDictionary + { + get { return _typesCannotResolve; } + } + protected virtual object DefaultCreateInstance(Type type) { return Activator.CreateInstance( diff --git a/src/UnityAdapter/HttpApplicationExtensions.cs b/src/UnityAdapter/HttpApplicationExtensions.cs index 3b93980..6fd5428 100644 --- a/src/UnityAdapter/HttpApplicationExtensions.cs +++ b/src/UnityAdapter/HttpApplicationExtensions.cs @@ -1,9 +1,12 @@ -using System; -using System.Web; -using Unity; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity { + using System; + using System.Web; + using global::Unity; + /// /// Extension methods of HttpApplication that help use Unity container /// diff --git a/src/UnityAdapter/Properties/AssemblyInfo.cs b/src/UnityAdapter/Properties/AssemblyInfo.cs index 4598c37..1aeb933 100644 --- a/src/UnityAdapter/Properties/AssemblyInfo.cs +++ b/src/UnityAdapter/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyProduct("Microsoft.AspNet.WebFormsDependencyInjection.Unity")] -[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyCopyright("\x00a9 Microsoft Corporation. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -22,3 +22,4 @@ using System.Runtime.InteropServices; // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("3e53288e-f0d1-4a06-8ff9-7dc8fadfdc62")] +[assembly: InternalsVisibleTo("Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] \ No newline at end of file diff --git a/src/UnityAdapter/UnityAdapter.cs b/src/UnityAdapter/UnityAdapter.cs index 3b5517f..ca0093b 100644 --- a/src/UnityAdapter/UnityAdapter.cs +++ b/src/UnityAdapter/UnityAdapter.cs @@ -1,8 +1,11 @@ -using System.Web; -using Unity; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity { + using System.Web; + using global::Unity; + /// /// Extension methods of HttpApplication that help use Unity container /// diff --git a/test/UnityAdapter.Test/35MSSharedLib1024.snk b/test/UnityAdapter.Test/35MSSharedLib1024.snk new file mode 100644 index 0000000..695f1b3 Binary files /dev/null and b/test/UnityAdapter.Test/35MSSharedLib1024.snk differ diff --git a/test/UnityAdapter.Test/Class1.cs b/test/UnityAdapter.Test/Class1.cs deleted file mode 100644 index 8756f49..0000000 --- a/test/UnityAdapter.Test/Class1.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace UnityAdapter.Test -{ - public class Class1 - { - } -} diff --git a/test/UnityAdapter.Test/ContainerServiceProviderTest.cs b/test/UnityAdapter.Test/ContainerServiceProviderTest.cs new file mode 100644 index 0000000..db37db1 --- /dev/null +++ b/test/UnityAdapter.Test/ContainerServiceProviderTest.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. + +namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test +{ + using Moq; + using Microsoft.AspNet.WebFormsDependencyInjection.Unity; + using System; + using Xunit; + using global::Unity.Exceptions; + using global::Unity; + using System.Web; + + public class ContainerServiceProviderTest + { + public ContainerServiceProviderTest() + { + HttpRuntime.WebObjectActivator = null; + } + + [Fact] + public void ContainerServiceProvider_Should_Preserve_Existing_ServiceProvider_And_Initialize_UnityContainer() + { + var existingSP = new Mock(); + var containerSP = new ContainerServiceProvider(existingSP.Object); + + Assert.Same(existingSP.Object, containerSP.NextServiceProvider); + Assert.NotNull(containerSP.Container); + } + + [Fact] + public void GetService_Should_Resolve_Type_EvenIf_Unity_Cannot_Resolve() + { + var containerSP = new ContainerServiceProvider(null); + var resolvedObj = containerSP.GetService(typeof(TypeToResolveBase)); + + Assert.NotNull(resolvedObj); + Assert.IsType(resolvedObj); + } + + [Fact] + public void GetService_Should_Use_Saved_ServiceProvider_If_UnityContainer_Cannot_Resolve() + { + var existingSP = new Mock(); + existingSP.Setup(sp => sp.GetService(typeof(TypeToResolveBase))).Returns(new TypeToResolve()); + var containerSP = new ContainerServiceProvider(existingSP.Object); + var resolvedObj = containerSP.GetService(typeof(TypeToResolveBase)); + + Assert.NotNull(resolvedObj); + Assert.IsType(resolvedObj); + } + + [Fact] + public void GetService_Should_Not_Try_UnityContainer_Again_If_UnityContainer_Failed_To_Resolve_A_Type() + { + var container = new Mock(); + var isFirstCall = true; + var secondCalled = false; + var typeToResolve = typeof(TypeToResolveBase); + + container.Setup(sp => sp.Resolve(typeToResolve, "", null)).Callback(() => + { + if(isFirstCall) + { + isFirstCall = false; + throw new ResolutionFailedException(typeToResolve, "", "", null); + } + else + { + secondCalled = true; + } + }); + var containerSP = new ContainerServiceProvider(null); + containerSP.Container = container.Object; + var resolvedObj = containerSP.GetService(typeToResolve); + Assert.NotNull(resolvedObj); + Assert.IsType(typeToResolve, resolvedObj); + + resolvedObj = containerSP.GetService(typeToResolve); + Assert.NotNull(resolvedObj); + Assert.IsType(typeToResolve, resolvedObj); + Assert.False(secondCalled); + } + + [Fact] + public void GetService_Should_Cache_Type_That_Cannot_Be_Resolved_By_UnityContainer() + { + var containerSP = new ContainerServiceProvider(null); + var resolvedObj = containerSP.GetService(typeof(TypeToResolveBase)); + + Assert.NotNull(resolvedObj); + Assert.IsType(resolvedObj); + Assert.True(containerSP.TypeCannotResolveDictionary.ContainsKey(typeof(TypeToResolveBase))); + } + } + + class TypeToResolveBase + { + protected TypeToResolveBase() { } + } + + class TypeToResolve : TypeToResolveBase + { + public TypeToResolve() { } + } +} diff --git a/test/UnityAdapter.Test/HttpApplicationExtensionsTest.cs b/test/UnityAdapter.Test/HttpApplicationExtensionsTest.cs new file mode 100644 index 0000000..048f10e --- /dev/null +++ b/test/UnityAdapter.Test/HttpApplicationExtensionsTest.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. + +namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test +{ + using Moq; + using System; + using System.Web; + using Xunit; + + public class HttpApplicationExtensionsTest + { + public HttpApplicationExtensionsTest() + { + HttpRuntime.WebObjectActivator = null; + } + + [Fact] + public void AddUnity_Should_Throw_ArgumentNullException_If_HttpApplication_Is_Null() + { + Assert.Throws(() => + { + ((HttpApplication)null).AddUnity(); + }); + } + + [Fact] + public void AddUnity_Should_Register_WebObjectActivator_With_ContainerServiceProvider() + { + var app = new HttpApplication(); + var container = app.AddUnity(); + + Assert.NotNull(container); + Assert.NotNull(HttpRuntime.WebObjectActivator); + Assert.IsType(HttpRuntime.WebObjectActivator); + } + + [Fact] + public void GetUnityContainer_Should_Return_UnityContainer() + { + var app = new HttpApplication(); + app.AddUnity(); + var container = app.GetUnityContainer(); + + Assert.NotNull(container); + } + + [Fact] + public void GetUnityContainer_Should_Return_Null_If_Registered_WebObjectActivator_Is_Not_ContainerServiceProvider() + { + var app = new HttpApplication(); + var existingSP = new Mock(); + HttpRuntime.WebObjectActivator = existingSP.Object; + + var container = app.GetUnityContainer(); + Assert.Null(container); + } + } +} diff --git a/test/UnityAdapter.Test/Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test.csproj b/test/UnityAdapter.Test/Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test.csproj index c9df8ad..6240aa9 100644 --- a/test/UnityAdapter.Test/Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test.csproj +++ b/test/UnityAdapter.Test/Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test.csproj @@ -1,5 +1,6 @@  + @@ -9,8 +10,8 @@ {071D67ED-B0B6-4927-A75D-83DDDC4DD60B} Library Properties - UnityAdapter.Test - UnityAdapter.Test + Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test + Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test v4.7.2 512 @@ -33,15 +34,40 @@ prompt 4 + + true + + + 35MSSharedLib1024.snk + + + true + + + ..\..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll + + + ..\..\packages\Moq.4.8.2\lib\net45\Moq.dll + + + + ..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + + ..\..\packages\System.ValueTuple.4.4.0\lib\net47\System.ValueTuple.dll + True + + + ..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll @@ -56,15 +82,27 @@ - + + + + + + + {3e53288e-f0d1-4a06-8ff9-7dc8fadfdc62} + Microsoft.AspNet.WebFormsDependencyInjection.Unity + + + + + @@ -74,6 +112,7 @@ + diff --git a/test/UnityAdapter.Test/UnityAdapterTest.cs b/test/UnityAdapter.Test/UnityAdapterTest.cs new file mode 100644 index 0000000..6675287 --- /dev/null +++ b/test/UnityAdapter.Test/UnityAdapterTest.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See the License.txt file in the project root for full license information. + +namespace Microsoft.AspNet.WebFormsDependencyInjection.Unity.Test +{ + using Moq; + using System; + using System.Web; + using Xunit; + + public class UnityAdapterTest + { + public UnityAdapterTest() + { + HttpRuntime.WebObjectActivator = null; + } + + [Fact] + public void AddUnity_Should_Register_WebObjectActivator_And_Return_UnityContainer() + { + var unityContainer = UnityAdapter.AddUnity(); + + Assert.NotNull(HttpRuntime.WebObjectActivator); + Assert.IsType(HttpRuntime.WebObjectActivator); + Assert.NotNull(unityContainer); + } + + [Fact] + public void AddUnity_Should_Chain_Existing_WebObjectActivator() + { + var existingSP = new Mock(); + HttpRuntime.WebObjectActivator = existingSP.Object; + + var unityContainer = UnityAdapter.AddUnity(); + + Assert.NotNull(HttpRuntime.WebObjectActivator); + Assert.IsType(HttpRuntime.WebObjectActivator); + Assert.Same(existingSP.Object, ((ContainerServiceProvider)HttpRuntime.WebObjectActivator).NextServiceProvider); + Assert.NotNull(unityContainer); + } + } +} diff --git a/test/UnityAdapter.Test/packages.config b/test/UnityAdapter.Test/packages.config index 203eae0..1ee1e95 100644 --- a/test/UnityAdapter.Test/packages.config +++ b/test/UnityAdapter.Test/packages.config @@ -1,5 +1,9 @@  + + + + @@ -8,4 +12,5 @@ + \ No newline at end of file