mirror of https://github.com/abpframework/abp.git
committed by
GitHub
40 changed files with 586 additions and 61 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,3 @@ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
[assembly:InternalsVisibleTo("Volo.Abp.GlobalFeatures.Tests")] |
|||
@ -0,0 +1,21 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.GlobalFeatures</AssemblyName> |
|||
<PackageId>Volo.Abp.GlobalFeatures</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public class AbpGlobalFeaturesModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public abstract class GlobalFeature |
|||
{ |
|||
[NotNull] |
|||
public GlobalModuleFeatures Module { get; } |
|||
|
|||
[NotNull] |
|||
public GlobalFeatureManager FeatureManager { get; } |
|||
|
|||
[NotNull] |
|||
public string FeatureName { get; } |
|||
|
|||
public bool IsEnabled |
|||
{ |
|||
get => FeatureManager.IsEnabled(FeatureName); |
|||
set => SetEnabled(value); |
|||
} |
|||
|
|||
protected GlobalFeature([NotNull] GlobalModuleFeatures module) |
|||
{ |
|||
Module = Check.NotNull(module, nameof(module)); |
|||
FeatureManager = Module.FeatureManager; |
|||
FeatureName = GlobalFeatureNameAttribute.GetName(GetType()); |
|||
} |
|||
|
|||
public virtual void Enable() |
|||
{ |
|||
FeatureManager.Enable(FeatureName); |
|||
} |
|||
|
|||
public virtual void Disable() |
|||
{ |
|||
FeatureManager.Disable(FeatureName); |
|||
} |
|||
|
|||
public void SetEnabled(bool isEnabled) |
|||
{ |
|||
if (isEnabled) |
|||
{ |
|||
Enable(); |
|||
} |
|||
else |
|||
{ |
|||
Disable(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public class GlobalFeatureDictionary : Dictionary<string, GlobalFeature> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public class GlobalFeatureManager |
|||
{ |
|||
public static GlobalFeatureManager Instance { get; protected set; } = new GlobalFeatureManager(); |
|||
|
|||
/// <summary>
|
|||
/// A common dictionary to store arbitrary configurations.
|
|||
/// </summary>
|
|||
[NotNull] |
|||
public Dictionary<object, object> Configuration { get; } |
|||
|
|||
public GlobalModuleFeaturesDictionary Modules { get; } |
|||
|
|||
protected HashSet<string> EnabledFeatures { get; } |
|||
|
|||
internal GlobalFeatureManager() |
|||
{ |
|||
EnabledFeatures = new HashSet<string>(); |
|||
Configuration = new Dictionary<object, object>(); |
|||
Modules = new GlobalModuleFeaturesDictionary(this); |
|||
} |
|||
|
|||
public virtual bool IsEnabled<TFeature>() |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
return IsEnabled(GlobalFeatureNameAttribute.GetName<TFeature>()); |
|||
} |
|||
|
|||
public virtual bool IsEnabled(string featureName) |
|||
{ |
|||
return EnabledFeatures.Contains(featureName); |
|||
} |
|||
|
|||
protected internal void Enable(string featureName) |
|||
{ |
|||
EnabledFeatures.AddIfNotContains(featureName); |
|||
} |
|||
|
|||
protected internal void Disable(string featureName) |
|||
{ |
|||
EnabledFeatures.Remove(featureName); |
|||
} |
|||
|
|||
public virtual IEnumerable<string> GetEnabledFeatureNames() |
|||
{ |
|||
return EnabledFeatures; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Class)] |
|||
public class GlobalFeatureNameAttribute : Attribute |
|||
{ |
|||
[NotNull] |
|||
public string Name { get; } |
|||
|
|||
public GlobalFeatureNameAttribute([NotNull] string name) |
|||
{ |
|||
Name = Check.NotNullOrWhiteSpace(name, nameof(name)); |
|||
} |
|||
|
|||
public static string GetName<TFeature>() |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
return GetName(typeof(TFeature)); |
|||
} |
|||
|
|||
[NotNull] |
|||
public static string GetName(Type type) |
|||
{ |
|||
var attribute = type |
|||
.GetCustomAttributes<GlobalFeatureNameAttribute>() |
|||
.FirstOrDefault(); |
|||
|
|||
if (attribute == null) |
|||
{ |
|||
throw new AbpException($"{type.AssemblyQualifiedName} should define the {typeof(GlobalFeatureNameAttribute).FullName} atttribute!"); |
|||
} |
|||
|
|||
return attribute |
|||
.As<GlobalFeatureNameAttribute>() |
|||
.Name; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public abstract class GlobalModuleFeatures |
|||
{ |
|||
[NotNull] |
|||
public GlobalFeatureManager FeatureManager { get; } |
|||
|
|||
[NotNull] |
|||
protected GlobalFeatureDictionary AllFeatures { get; } |
|||
|
|||
protected GlobalModuleFeatures( |
|||
[NotNull] GlobalFeatureManager featureManager) |
|||
{ |
|||
FeatureManager = Check.NotNull(featureManager, nameof(featureManager)); |
|||
AllFeatures = new GlobalFeatureDictionary(); |
|||
} |
|||
|
|||
public virtual void Enable<TFeature>() |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
GetFeature<TFeature>().Enable(); |
|||
} |
|||
|
|||
public virtual void Disable<TFeature>() |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
GetFeature<TFeature>().Disable(); |
|||
} |
|||
|
|||
public virtual void SetEnabled<TFeature>(bool isEnabled) |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
GetFeature<TFeature>().SetEnabled(isEnabled); |
|||
} |
|||
|
|||
public virtual void Enable(string featureName) |
|||
{ |
|||
GetFeature(featureName).Enable(); |
|||
} |
|||
|
|||
public virtual void Disable(string featureName) |
|||
{ |
|||
GetFeature(featureName).Disable(); |
|||
} |
|||
|
|||
public virtual void SetEnabled(string featureName, bool isEnabled) |
|||
{ |
|||
GetFeature(featureName).SetEnabled(isEnabled); |
|||
} |
|||
|
|||
public virtual void EnableAll() |
|||
{ |
|||
foreach (var feature in AllFeatures.Values) |
|||
{ |
|||
feature.Enable(); |
|||
} |
|||
} |
|||
|
|||
public virtual void DisableAll() |
|||
{ |
|||
foreach (var feature in AllFeatures.Values) |
|||
{ |
|||
feature.Disable(); |
|||
} |
|||
} |
|||
|
|||
public virtual GlobalFeature GetFeature(string featureName) |
|||
{ |
|||
var feature = AllFeatures.GetOrDefault(featureName); |
|||
if (feature == null) |
|||
{ |
|||
throw new AbpException($"There is no feature defined by name '{featureName}'."); |
|||
} |
|||
|
|||
return feature; |
|||
} |
|||
|
|||
public virtual TFeature GetFeature<TFeature>() |
|||
where TFeature : GlobalFeature |
|||
{ |
|||
return (TFeature) GetFeature(GlobalFeatureNameAttribute.GetName<TFeature>()); |
|||
} |
|||
|
|||
public virtual IReadOnlyList<GlobalFeature> GetFeatures() |
|||
{ |
|||
return AllFeatures.Values.ToImmutableList(); |
|||
} |
|||
|
|||
protected void AddFeature(GlobalFeature feature) |
|||
{ |
|||
AllFeatures[feature.FeatureName] = feature; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public class GlobalModuleFeaturesDictionary : Dictionary<string, GlobalModuleFeatures> |
|||
{ |
|||
public GlobalFeatureManager FeatureManager { get; } |
|||
|
|||
public GlobalModuleFeaturesDictionary( |
|||
[NotNull] GlobalFeatureManager featureManager) |
|||
{ |
|||
FeatureManager = Check.NotNull(featureManager, nameof(featureManager)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.test.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,23 @@ |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public class GlobalFeatureManager_Tests |
|||
{ |
|||
private readonly GlobalFeatureManager _featureManeger; |
|||
|
|||
public GlobalFeatureManager_Tests() |
|||
{ |
|||
_featureManeger = new GlobalFeatureManager(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Enable_Feature_By_Name() |
|||
{ |
|||
_featureManeger.IsEnabled("Feature1").ShouldBeFalse(); |
|||
_featureManeger.Enable("Feature1"); |
|||
_featureManeger.IsEnabled("Feature1").ShouldBeTrue(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using Volo.Abp.GlobalFeatures; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.CmsKit |
|||
{ |
|||
public static class FeatureConfigurer |
|||
{ |
|||
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); |
|||
|
|||
public static void Configure() |
|||
{ |
|||
OneTimeRunner.Run(() => |
|||
{ |
|||
GlobalFeatureManager.Instance.Modules.CmsKit().EnableAll(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Volo.CmsKit.GlobalFeatures; |
|||
|
|||
namespace Volo.Abp.GlobalFeatures |
|||
{ |
|||
public static class GlobalModuleFeaturesDictionaryCmsKitExtensions |
|||
{ |
|||
public static GlobalCmsKitFeatures CmsKit( |
|||
[NotNull] this GlobalModuleFeaturesDictionary modules) |
|||
{ |
|||
Check.NotNull(modules, nameof(modules)); |
|||
|
|||
return modules |
|||
.GetOrAdd( |
|||
GlobalCmsKitFeatures.ModuleName, |
|||
_ => new GlobalCmsKitFeatures(modules.FeatureManager) |
|||
) |
|||
as GlobalCmsKitFeatures; |
|||
} |
|||
|
|||
public static GlobalModuleFeaturesDictionary CmsKit( |
|||
[NotNull] this GlobalModuleFeaturesDictionary modules, |
|||
[NotNull] Action<GlobalCmsKitFeatures> configureAction) |
|||
{ |
|||
Check.NotNull(configureAction, nameof(configureAction)); |
|||
|
|||
configureAction(modules.CmsKit()); |
|||
|
|||
return modules; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.GlobalFeatures; |
|||
|
|||
namespace Volo.CmsKit.GlobalFeatures |
|||
{ |
|||
[GlobalFeatureName(Name)] |
|||
public class CommentsFeature : GlobalFeature |
|||
{ |
|||
public const string Name = "CmsKit.Comments"; |
|||
|
|||
internal CommentsFeature( |
|||
[NotNull] GlobalCmsKitFeatures cmsKit |
|||
) : base(cmsKit) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.GlobalFeatures; |
|||
|
|||
namespace Volo.CmsKit.GlobalFeatures |
|||
{ |
|||
public class GlobalCmsKitFeatures : GlobalModuleFeatures |
|||
{ |
|||
public const string ModuleName = "CmsKit"; |
|||
|
|||
public ReactionsFeature Reactions => GetFeature<ReactionsFeature>(); |
|||
|
|||
public CommentsFeature Comments => GetFeature<CommentsFeature>(); |
|||
|
|||
public GlobalCmsKitFeatures([NotNull] GlobalFeatureManager featureManager) |
|||
: base(featureManager) |
|||
{ |
|||
AddFeature(new ReactionsFeature(this)); |
|||
AddFeature(new CommentsFeature(this)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.GlobalFeatures; |
|||
|
|||
namespace Volo.CmsKit.GlobalFeatures |
|||
{ |
|||
[GlobalFeatureName(Name)] |
|||
public class ReactionsFeature : GlobalFeature |
|||
{ |
|||
public const string Name = "CmsKit.Reactions"; |
|||
|
|||
internal ReactionsFeature( |
|||
[NotNull] GlobalCmsKitFeatures cmsKit |
|||
) : base(cmsKit) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,19 +1,10 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.CmsKit.Comments; |
|||
using Volo.CmsKit.Reactions; |
|||
using Volo.CmsKit.Users; |
|||
|
|||
namespace Volo.CmsKit.EntityFrameworkCore |
|||
{ |
|||
[ConnectionStringName(CmsKitDbProperties.ConnectionStringName)] |
|||
public interface ICmsKitDbContext : IEfCoreDbContext |
|||
{ |
|||
DbSet<UserReaction> UserReactions { get; } |
|||
|
|||
DbSet<Comment> Comments { get; } |
|||
|
|||
DbSet<CmsUser> CmsUsers { get; set; } |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue