mirror of https://github.com/abpframework/abp.git
11 changed files with 340 additions and 1 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:53900/", |
||||
|
"sslPort": 44362 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"Volo.Abp.SignalR": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
}, |
||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp3.1</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.SignalR</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.SignalR</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<IsPackable>true</IsPackable> |
||||
|
<OutputType>Library</OutputType> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,115 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Reflection; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Http.Connections; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.SignalR |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreSignalRModule : AbpModule |
||||
|
{ |
||||
|
private static readonly MethodInfo MapHubGenericMethodInfo = |
||||
|
typeof(AbpAspNetCoreSignalRModule) |
||||
|
.GetMethod("MapHub", BindingFlags.Static | BindingFlags.NonPublic); |
||||
|
|
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddConventionalRegistrar(new AbpSignalRConventionalRegistrar()); |
||||
|
|
||||
|
AutoAddHubTypes(context.Services); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddSignalR(); |
||||
|
|
||||
|
Configure<AbpEndpointRouterOptions>(options => |
||||
|
{ |
||||
|
options.EndpointConfigureActions.Add(endpointContext => |
||||
|
{ |
||||
|
var signalROptions = endpointContext |
||||
|
.ScopeServiceProvider |
||||
|
.GetRequiredService<IOptions<AbpSignalROptions>>() |
||||
|
.Value; |
||||
|
|
||||
|
foreach (var hubConfig in signalROptions.Hubs) |
||||
|
{ |
||||
|
MapHubType( |
||||
|
hubConfig.HubType, |
||||
|
endpointContext.Endpoints, |
||||
|
hubConfig.RoutePattern, |
||||
|
opts => |
||||
|
{ |
||||
|
foreach (var configureAction in hubConfig.ConfigureActions) |
||||
|
{ |
||||
|
configureAction(opts); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void AutoAddHubTypes(IServiceCollection services) |
||||
|
{ |
||||
|
var hubTypes = new List<Type>(); |
||||
|
|
||||
|
services.OnRegistred(context => |
||||
|
{ |
||||
|
if (typeof(Hub).IsAssignableFrom(context.ImplementationType)) |
||||
|
{ |
||||
|
hubTypes.Add(context.ImplementationType); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
services.Configure<AbpSignalROptions>(options => |
||||
|
{ |
||||
|
foreach (var hubType in hubTypes) |
||||
|
{ |
||||
|
options.Hubs.Add(HubConfig.Create(hubType)); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void MapHubType( |
||||
|
Type hubType, |
||||
|
IEndpointRouteBuilder endpoints, |
||||
|
string pattern, |
||||
|
Action<HttpConnectionDispatcherOptions> configureOptions) |
||||
|
{ |
||||
|
MapHubGenericMethodInfo |
||||
|
.MakeGenericMethod(hubType) |
||||
|
.Invoke( |
||||
|
this, |
||||
|
new object[] |
||||
|
{ |
||||
|
endpoints, |
||||
|
pattern, |
||||
|
configureOptions |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
// ReSharper disable once UnusedMember.Local (used via reflection)
|
||||
|
private static void MapHub<THub>( |
||||
|
IEndpointRouteBuilder endpoints, |
||||
|
string pattern, |
||||
|
Action<HttpConnectionDispatcherOptions> configureOptions) |
||||
|
where THub : Hub |
||||
|
{ |
||||
|
endpoints.MapHub<THub>( |
||||
|
pattern, |
||||
|
configureOptions |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.SignalR |
||||
|
{ |
||||
|
public class AbpSignalRConventionalRegistrar : ConventionalRegistrarBase |
||||
|
{ |
||||
|
public override void AddType(IServiceCollection services, Type type) |
||||
|
{ |
||||
|
if (IsConventionalRegistrationDisabled(type)) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!IsHub(type)) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type); |
||||
|
|
||||
|
TriggerServiceExposing(services, type, serviceTypes); |
||||
|
|
||||
|
foreach (var serviceType in serviceTypes) |
||||
|
{ |
||||
|
services.Add( |
||||
|
ServiceDescriptor.Describe( |
||||
|
serviceType, |
||||
|
type, |
||||
|
ServiceLifetime.Transient |
||||
|
) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static bool IsHub(Type type) |
||||
|
{ |
||||
|
return typeof(Hub).IsAssignableFrom(type); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.SignalR |
||||
|
{ |
||||
|
public class AbpSignalROptions |
||||
|
{ |
||||
|
public List<HubConfig> Hubs { get; } |
||||
|
|
||||
|
public AbpSignalROptions() |
||||
|
{ |
||||
|
Hubs = new List<HubConfig>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.AspNetCore.Http.Connections; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.SignalR |
||||
|
{ |
||||
|
public class HubConfig |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public Type HubType { get; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public string RoutePattern { get; set; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public List<Action<HttpConnectionDispatcherOptions>> ConfigureActions { get; set; } |
||||
|
|
||||
|
public HubConfig( |
||||
|
[NotNull] Type hubType, |
||||
|
[NotNull] string routePattern) |
||||
|
{ |
||||
|
HubType = Check.NotNull(hubType, nameof(hubType)); |
||||
|
RoutePattern = Check.NotNullOrWhiteSpace(routePattern, nameof(routePattern)); |
||||
|
ConfigureActions = new List<Action<HttpConnectionDispatcherOptions>>(); |
||||
|
} |
||||
|
|
||||
|
public static HubConfig Create<THub>() |
||||
|
where THub : Hub |
||||
|
{ |
||||
|
return Create(typeof(THub)); |
||||
|
} |
||||
|
|
||||
|
public static HubConfig Create(Type hubType) |
||||
|
{ |
||||
|
return new HubConfig( |
||||
|
hubType, |
||||
|
HubRouteAttribute.GetRoutePattern(hubType) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using System.Reflection; |
||||
|
using Microsoft.AspNetCore.SignalR; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.SignalR |
||||
|
{ |
||||
|
public class HubRouteAttribute : Attribute |
||||
|
{ |
||||
|
public string RoutePattern { get; set; } |
||||
|
|
||||
|
public HubRouteAttribute(string routePattern) |
||||
|
{ |
||||
|
RoutePattern = routePattern; |
||||
|
} |
||||
|
|
||||
|
public static string GetRoutePattern<THub>() |
||||
|
where THub : Hub |
||||
|
{ |
||||
|
return GetRoutePattern(typeof(THub)); |
||||
|
} |
||||
|
|
||||
|
public static string GetRoutePattern(Type hubType) |
||||
|
{ |
||||
|
var routeAttribute = hubType.GetSingleAttributeOrNull<HubRouteAttribute>(); |
||||
|
if (routeAttribute != null) |
||||
|
{ |
||||
|
return routeAttribute.RoutePattern; |
||||
|
} |
||||
|
|
||||
|
return "/signalr-hubs/" + hubType.Name.RemovePostFix("Hub").ToKebabCase(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue