增加全局的功能容器

This commit is contained in:
sanchime 2023-04-09 16:22:54 +08:00
parent 976b6fb15d
commit 50159e869f
12 changed files with 118 additions and 164 deletions

View File

@ -7,8 +7,4 @@
<RootNamespace>Demo</RootNamespace> <RootNamespace>Demo</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Folder Include="Extensions" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,8 @@
using Demo.Features;
namespace Demo.Extensions;
public static class FeatureContainerExtensions
{
}

View File

@ -8,30 +8,20 @@ namespace Demo.Features;
/// <typeparam name="TMetadata"></typeparam> /// <typeparam name="TMetadata"></typeparam>
public sealed class DefaultFeature : Feature public sealed class DefaultFeature : Feature
{ {
public DefaultFeature(string name, FeatureFunction? executeFunction = null, public DefaultFeature(string name,
FeatureFunctionAsync? executeFunctionAsync = null, FeatureFunction? executeFunction = null,
int order = 1) int order = 1)
{ {
_executeFunction = executeFunction; _executeFunction = executeFunction;
_executeFunctionAsync = executeFunctionAsync;
Name = name; Name = name;
Order = order; Order = order;
} }
private readonly FeatureFunction? _executeFunction; private readonly FeatureFunction? _executeFunction;
private readonly FeatureFunctionAsync? _executeFunctionAsync;
public override void Execute(IMetadata metadata) public override void Execute(IMetadata metadata)
{ {
_executeFunction?.Invoke(this, metadata); _executeFunction?.Invoke(this, metadata);
} }
public override async ValueTask ExecuteAsync(IMetadata metadata)
{
if (_executeFunctionAsync is not null)
{
await _executeFunctionAsync.Invoke(this, metadata);
}
}
} }

View File

@ -18,23 +18,11 @@ public abstract class Feature
public abstract void Execute(IMetadata metadata); public abstract void Execute(IMetadata metadata);
public virtual ValueTask ExecuteAsync(IMetadata metadata)
{
Execute(metadata);
return ValueTask.CompletedTask;
}
public virtual void OnException(FeatureExceptionContext context) public virtual void OnException(FeatureExceptionContext context)
{ {
throw context.Exception; throw context.Exception;
} }
public virtual ValueTask OnExceptionAsync(FeatureExceptionContext context)
{
throw context.Exception;
}
} }
public delegate void FeatureFunction(Feature feature, IMetadata metadata); public delegate void FeatureFunction(Feature feature, IMetadata metadata);
public delegate ValueTask FeatureFunctionAsync(Feature feature, IMetadata metadata);

View File

@ -0,0 +1,51 @@
using System.Collections.Immutable;
using Demo.Models;
namespace Demo.Features;
public class FeatureContainer : IFeatureContainer
{
private readonly IDictionary<string, FeatureList> _payloads;
private static readonly Lazy<FeatureContainer> _lazy = new Lazy<FeatureContainer>(() => new FeatureContainer());
private FeatureContainer()
{
_payloads = new Dictionary<string, FeatureList>();
}
public static FeatureContainer Instance => _lazy.Value;
public IFeatureContainer RegisterFeature(string signId, Feature feature)
{
if (_payloads.TryGetValue(signId, out var features))
{
features.TryAdd(feature.Name, feature);
}
else
{
_payloads.TryAdd(signId, new FeatureList() { { feature.Name, feature } });
}
return this;
}
public IFeatureContainer RegisterWrapper(Func<IMetadata, FeatureList, IFeatureWrapper> wrapper)
{
_wrapper = wrapper;
return this;
}
private Func<IMetadata, FeatureList, IFeatureWrapper>? _wrapper;
public IFeatureWrapper BuildWrapper(IMetadata metadata)
{
if (_payloads.TryGetValue(metadata.SignId, out var features))
{
return _wrapper?.Invoke(metadata, features) ?? new FeatureWrapper(metadata, features);
}
return new FeatureWrapper(metadata, features);
}
}

View File

@ -7,8 +7,7 @@ namespace Demo.Features;
/// 功能列表容器 /// 功能列表容器
/// </summary> /// </summary>
/// <typeparam name="TMetadata"></typeparam> /// <typeparam name="TMetadata"></typeparam>
public class FeatureList<TMetadata> : Dictionary<string, Feature> public class FeatureList : Dictionary<string, Feature>
where TMetadata : IMetadata
{ {
public FeatureList(IDictionary<string, Feature>? list = null) public FeatureList(IDictionary<string, Feature>? list = null)
: base(list ?? new Dictionary<string, Feature>()) : base(list ?? new Dictionary<string, Feature>())

View File

@ -3,93 +3,16 @@ using Demo.Models;
namespace Demo.Features; namespace Demo.Features;
public class FeatureWrapper<TMetadata> public class FeatureWrapper : IFeatureWrapper
where TMetadata : IMetadata
{ {
private readonly TMetadata _metadata; private readonly IMetadata _metadata;
protected FeatureList<TMetadata> Features { get; } protected FeatureList Features { get; }
public FeatureWrapper(TMetadata metadata, FeatureList<TMetadata>? features = null) public FeatureWrapper(IMetadata metadata, FeatureList? features = null)
{ {
_metadata = metadata; _metadata = metadata;
Features = features ?? new FeatureList<TMetadata>(); Features = features ?? new FeatureList();
}
public FeatureWrapper<TMetadata> DropFeature(string name)
{
if (String.IsNullOrWhiteSpace(name))
{
throw new CheckoutException("功能名称不能为空或空白字符");
}
Features.Remove(name);
return this;
}
/// <summary>
/// 添加功能
/// </summary>
/// <param name="feature"></param>
/// <typeparam name="TFeature"></typeparam>
/// <returns></returns>
public FeatureWrapper<TMetadata> WithFeature<TFeature>(TFeature feature)
where TFeature : Feature
{
if (feature is null)
{
return this;
}
if (String.IsNullOrWhiteSpace(feature.Name))
{
throw new CheckoutException("功能名称不能为空或空白字符");
}
Features.TryAdd(feature.Name, feature);
return this;
}
/// <summary>
/// 添加功能
/// </summary>
/// <param name="name"></param>
/// <param name="feature"></param>
/// <param name="order"></param>
/// <returns></returns>
public FeatureWrapper<TMetadata> WithFeature(string name, FeatureFunction feature, int order = 1)
{
if (String.IsNullOrWhiteSpace(name))
{
throw new CheckoutException("功能名称不能为空或空白字符");
}
if (feature is not null)
{
Features.TryAdd(name, new DefaultFeature(name, feature, order: order));
}
return this;
}
/// <summary>
/// 添加功能
/// </summary>
/// <param name="name"></param>
/// <param name="feature"></param>
/// <param name="order"></param>
/// <returns></returns>
public FeatureWrapper<TMetadata> WithFeature(string name, FeatureFunctionAsync feature, int order = 1)
{
if (String.IsNullOrWhiteSpace(name))
{
throw new CheckoutException("功能名称不能为空或空白字符");
}
if (feature is not null)
{
Features.TryAdd(name, new DefaultFeature(name, executeFunctionAsync: feature, order: order));
}
return this;
} }
public void ExecuteAll() public void ExecuteAll()
@ -122,23 +45,4 @@ public class FeatureWrapper<TMetadata>
throw new KeyNotFoundException(name); throw new KeyNotFoundException(name);
} }
} }
public async ValueTask ExecuteAllAsync()
{
foreach (var feature in Features.Values.OrderBy(f => f.Order))
{
try
{
await feature.ExecuteAsync(_metadata);
if (feature.Finished)
{
break;
}
}
catch (Exception ex)
{
await feature.OnExceptionAsync(new FeatureExceptionContext(feature, new FeatureException(_metadata, feature, ex)));
}
}
}
} }

View File

@ -0,0 +1,15 @@
using Demo.Models;
namespace Demo.Features;
/// <summary>
/// 功能容器
/// </summary>
public interface IFeatureContainer
{
IFeatureContainer RegisterFeature(string signId, Feature feature);
IFeatureContainer RegisterWrapper(Func<IMetadata, FeatureList, IFeatureWrapper> wrapper);
IFeatureWrapper BuildWrapper(IMetadata metadata);
}

View File

@ -0,0 +1,8 @@
namespace Demo.Features;
public interface IFeatureWrapper
{
void ExecuteAll();
void Execute(string name);
}

View File

@ -5,7 +5,7 @@ namespace Demo.Models;
public abstract class Chip : IMetadata public abstract class Chip : IMetadata
{ {
public abstract Guid SignId { get; } public abstract string SignId { get; }
/// <summary> /// <summary>
/// 属性 /// 属性
/// </summary> /// </summary>
@ -18,7 +18,7 @@ public abstract class Chip : IMetadata
/// <summary> /// <summary>
/// 功能 /// 功能
/// </summary> /// </summary>
public virtual FeatureWrapper<Chip> Features { get; } public IFeatureWrapper Features { get; }
/// <summary> /// <summary>
/// 公式 /// 公式
@ -35,7 +35,8 @@ public abstract class Chip : IMetadata
{ {
Properties = new MetadataPropertySet(); Properties = new MetadataPropertySet();
} }
Features = new FeatureWrapper<Chip>(this);
Features = FeatureContainer.Instance.BuildWrapper(this);
Formula = new FormulaExecutor(null, null); Formula = new FormulaExecutor(null, null);
Initialize(); Initialize();
} }

View File

@ -9,7 +9,7 @@ public interface IMetadata
{ {
string Name { get; } string Name { get; }
Guid SignId { get; } string SignId { get; }
/// <summary> /// <summary>
/// 属性 /// 属性
/// </summary> /// </summary>

View File

@ -1,22 +1,23 @@
using Demo.Models; using Demo.Features;
using Demo.Models;
try try
{ {
FeatureContainer.Instance
.RegisterWrapper((m, f) => new FeatureWrapper(m, f)) // 注册功能调用包装器可以不写默认是FeatureWrapper
.RegisterFeature("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4", new DefaultFeature("场频自适应功能", // 注册功能
(feature, metadata) =>
{
Console.WriteLine("调用场频自适应功能");
}));
IcndChip icndChip = new IcndChip(); IcndChip icndChip = new IcndChip();
icndChip.SetProperty("Code", "1234") icndChip.SetProperty("Code", "1234")
.SetProperty("Name", "芯片"); .SetProperty("Name", "芯片");
icndChip.Features.ExecuteAll(); // 执行所有功能
icndChip.Features
.DropFeature("场频自适应功能")
.ExecuteAll();
icndChip.Features.Execute("场频自适应功能"); icndChip.Features.Execute("场频自适应功能");
icndChip.Formula.Compute(new FormulaExecutionContext() // 计算公式(需要调整) icndChip.Features.Execute("测试");
{
});
Console.WriteLine(icndChip.GetProperty<string>("Code")); Console.WriteLine(icndChip.GetProperty<string>("Code"));
} }
@ -26,18 +27,11 @@ catch (Exception ex)
} }
public class IcndChip : Chip public class IcndChip : Chip
{ {
public override Guid SignId => Guid.Parse("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4"); public override string SignId => "F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4";
protected override void Initialize() protected override void Initialize()
{ {
Name = "ICND芯片"; Name = "ICND芯片";
Features.WithFeature("场频自适应功能", (f, m) =>
{
Console.WriteLine($"{m.Name}调用{f.Name}");
}).WithFeature("其他功能", (f, m) =>
{
Console.WriteLine($"{m.Name}调用{f.Name},得到属性[\"Code\"]值{m.GetProperty<string>("Code")}");
});
} }
} }