Move the HostFactoryResolver to Extensions (dotnet/extensions#925)
\n\nCommit migrated from 9cd9cea398
This commit is contained in:
parent
ee6763d146
commit
4de3b5e105
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting
|
||||
{
|
||||
internal class HostFactoryResolver
|
||||
{
|
||||
public static readonly string BuildWebHost = nameof(BuildWebHost);
|
||||
public static readonly string CreateWebHostBuilder = nameof(CreateWebHostBuilder);
|
||||
public static readonly string CreateHostBuilder = nameof(CreateHostBuilder);
|
||||
|
||||
public static Func<string[], TWebHost> ResolveWebHostFactory<TWebHost>(Assembly assembly)
|
||||
{
|
||||
return ResolveFactory<TWebHost>(assembly, BuildWebHost);
|
||||
}
|
||||
|
||||
public static Func<string[], TWebHostBuilder> ResolveWebHostBuilderFactory<TWebHostBuilder>(Assembly assembly)
|
||||
{
|
||||
return ResolveFactory<TWebHostBuilder>(assembly, CreateWebHostBuilder);
|
||||
}
|
||||
|
||||
public static Func<string[], THostBuilder> ResolveHostBuilderFactory<THostBuilder>(Assembly assembly)
|
||||
{
|
||||
return ResolveFactory<THostBuilder>(assembly, CreateHostBuilder);
|
||||
}
|
||||
|
||||
private static Func<string[], T> ResolveFactory<T>(Assembly assembly, string name)
|
||||
{
|
||||
var programType = assembly?.EntryPoint?.DeclaringType;
|
||||
if (programType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var factory = programType.GetTypeInfo().GetDeclaredMethod(name);
|
||||
if (!IsFactory<T>(factory))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return args => (T)factory.Invoke(null, new object[] { args });
|
||||
}
|
||||
|
||||
// TReturn Factory(string[] args);
|
||||
private static bool IsFactory<TReturn>(MethodInfo factory)
|
||||
{
|
||||
return factory != null
|
||||
&& typeof(TReturn).IsAssignableFrom(factory.ReturnType)
|
||||
&& factory.GetParameters().Length == 1
|
||||
&& typeof(string[]).Equals(factory.GetParameters()[0].ParameterType);
|
||||
}
|
||||
|
||||
// Used by EF tooling without any Hosting references. Looses some return type safety checks.
|
||||
public static Func<string[], IServiceProvider> ResolveServiceProviderFactory(Assembly assembly)
|
||||
{
|
||||
// Prefer the older patterns by default for back compat.
|
||||
var webHostFactory = ResolveWebHostFactory<object>(assembly);
|
||||
if (webHostFactory != null)
|
||||
{
|
||||
return args =>
|
||||
{
|
||||
var webHost = webHostFactory(args);
|
||||
return GetServiceProvider(webHost);
|
||||
};
|
||||
}
|
||||
|
||||
var webHostBuilderFactory = ResolveWebHostBuilderFactory<object>(assembly);
|
||||
if (webHostBuilderFactory != null)
|
||||
{
|
||||
return args =>
|
||||
{
|
||||
var webHostBuilder = webHostBuilderFactory(args);
|
||||
var webHost = Build(webHostBuilder);
|
||||
return GetServiceProvider(webHost);
|
||||
};
|
||||
}
|
||||
|
||||
var hostBuilderFactory = ResolveHostBuilderFactory<object>(assembly);
|
||||
if (hostBuilderFactory != null)
|
||||
{
|
||||
return args =>
|
||||
{
|
||||
var hostBuilder = hostBuilderFactory(args);
|
||||
var host = Build(hostBuilder);
|
||||
return GetServiceProvider(host);
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object Build(object builder)
|
||||
{
|
||||
var buildMethod = builder.GetType().GetMethod("Build");
|
||||
return buildMethod?.Invoke(builder, Array.Empty<object>());
|
||||
}
|
||||
|
||||
private static IServiceProvider GetServiceProvider(object host)
|
||||
{
|
||||
if (host == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var hostType = host.GetType();
|
||||
var servicesProperty = hostType.GetTypeInfo().GetDeclaredProperty("Services");
|
||||
return (IServiceProvider)servicesProperty.GetValue(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Extensions.Hosting.Tests
|
||||
{
|
||||
public class HostFactoryResolverTests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildWebHostPattern_CanFindWebHost()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveWebHostFactory<IWebHost>(typeof(BuildWebHostPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IWebHost>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildWebHostPattern_CanFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(BuildWebHostPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IServiceProvider>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildWebHostPattern__Invalid_CantFindWebHost()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveWebHostFactory<IWebHost>(typeof(BuildWebHostInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.Null(factory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildWebHostPattern__Invalid_CantFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(BuildWebHostInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.Null(factory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateWebHostBuilderPattern_CanFindWebHostBuilder()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveWebHostBuilderFactory<IWebHostBuilder>(typeof(CreateWebHostBuilderPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IWebHostBuilder>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateWebHostBuilderPattern_CanFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(CreateWebHostBuilderPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IServiceProvider>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateWebHostBuilderPattern__Invalid_CantFindWebHostBuilder()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveWebHostBuilderFactory<IWebHostBuilder>(typeof(CreateWebHostBuilderInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.Null(factory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateWebHostBuilderPattern__InvalidReturnType_CanFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(CreateWebHostBuilderInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.Null(factory(Array.Empty<string>()));
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateHostBuilderPattern_CanFindHostBuilder()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveHostBuilderFactory<IHostBuilder>(typeof(CreateHostBuilderPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IHostBuilder>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateHostBuilderPattern_CanFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(CreateHostBuilderPatternTestSite.Program).Assembly);
|
||||
|
||||
Assert.NotNull(factory);
|
||||
Assert.IsAssignableFrom<IServiceProvider>(factory(Array.Empty<string>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateHostBuilderPattern__Invalid_CantFindHostBuilder()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveHostBuilderFactory<IHostBuilder>(typeof(CreateHostBuilderInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.Null(factory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateHostBuilderPattern__Invalid_CantFindServiceProvider()
|
||||
{
|
||||
var factory = HostFactoryResolver.ResolveServiceProviderFactory(typeof(CreateHostBuilderInvalidSignature.Program).Assembly);
|
||||
|
||||
Assert.Null(factory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,16 @@
|
|||
" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\testassets\BuildWebHostInvalidSignature\BuildWebHostInvalidSignature.csproj" />
|
||||
<ProjectReference Include="..\testassets\BuildWebHostPatternTestSite\BuildWebHostPatternTestSite.csproj" />
|
||||
<ProjectReference Include="..\testassets\CreateHostBuilderInvalidSignature\CreateHostBuilderInvalidSignature.csproj" />
|
||||
<ProjectReference Include="..\testassets\CreateHostBuilderPatternTestSite\CreateHostBuilderPatternTestSite.csproj" />
|
||||
<ProjectReference Include="..\testassets\CreateWebHostBuilderInvalidSignature\CreateWebHostBuilderInvalidSignature.csproj" />
|
||||
<ProjectReference Include="..\testassets\CreateWebHostBuilderPatternTestSite\CreateWebHostBuilderPatternTestSite.csproj" />
|
||||
<ProjectReference Include="..\testassets\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Threading.Tasks.Extensions" />
|
||||
<Reference Include="System.Security.Cryptography.Cng" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace BuildWebHostInvalidSignature
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
}
|
||||
|
||||
// Missing string[] args
|
||||
public static IWebHost BuildWebHost() => null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace BuildWebHostPatternTestSite
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
}
|
||||
|
||||
public static IWebHost BuildWebHost(string[] args) => new WebHost();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace CreateHostBuilderInvalidSignature
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var webHost = CreateHostBuilder(null, args).Build();
|
||||
}
|
||||
|
||||
// Extra parameter
|
||||
private static IHostBuilder CreateHostBuilder(object extraParam, string[] args) => null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace CreateHostBuilderPatternTestSite
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var webHost = CreateHostBuilder(args).Build();
|
||||
}
|
||||
|
||||
// Do not change the signature of this method. It's used for tests.
|
||||
private static HostBuilder CreateHostBuilder(string[] args) =>
|
||||
new HostBuilder();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace CreateWebHostBuilderInvalidSignature
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
}
|
||||
|
||||
// Wrong return type
|
||||
public static IWebHost CreateWebHostBuilder(string[] args) => new WebHost();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using MockHostTypes;
|
||||
|
||||
namespace CreateWebHostBuilderPatternTestSite
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var webHost = CreateWebHostBuilder(args).Build();
|
||||
}
|
||||
|
||||
// Do not change the signature of this method. It's used for tests.
|
||||
private static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public class Host : IHost
|
||||
{
|
||||
public IServiceProvider Services { get; } = new ServiceProvider();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public class HostBuilder : IHostBuilder
|
||||
{
|
||||
public IHost Build() => new Host();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public interface IHost
|
||||
{
|
||||
IServiceProvider Services { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public interface IHostBuilder
|
||||
{
|
||||
IHost Build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public interface IWebHost
|
||||
{
|
||||
IServiceProvider Services { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public interface IWebHostBuilder
|
||||
{
|
||||
IWebHost Build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public class ServiceProvider : IServiceProvider
|
||||
{
|
||||
public object GetService(Type serviceType) => null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public class WebHost : IWebHost
|
||||
{
|
||||
public IServiceProvider Services { get; } = new ServiceProvider();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace MockHostTypes
|
||||
{
|
||||
public class WebHostBuilder : IWebHostBuilder
|
||||
{
|
||||
public IWebHost Build() => new WebHost();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue