增加全局的功能容器
This commit is contained in:
parent
976b6fb15d
commit
50159e869f
|
@ -7,8 +7,4 @@
|
||||||
<RootNamespace>Demo</RootNamespace>
|
<RootNamespace>Demo</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Extensions" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
using Demo.Features;
|
||||||
|
|
||||||
|
namespace Demo.Extensions;
|
||||||
|
|
||||||
|
public static class FeatureContainerExtensions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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);
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>())
|
||||||
|
|
|
@ -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)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Demo.Features;
|
||||||
|
|
||||||
|
public interface IFeatureWrapper
|
||||||
|
{
|
||||||
|
void ExecuteAll();
|
||||||
|
|
||||||
|
void Execute(string name);
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ public interface IMetadata
|
||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
Guid SignId { get; }
|
string SignId { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 属性
|
/// 属性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -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")}");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue