refactor: unify binding & data provider interfaces
- Removed BindingType enum and all related logic from Binding. - Made Binding implement new IBinding and IKeyed interfaces. - Moved node selection logic to IBinding.Select; removed Resolve* methods from Binding. - Added new IBinding interface for XPath/CssPath selection. - Refactored IDataProvider to generic IDataProvider<T>; removed GetNode. - Updated ListContentDataProvider and ParagraphedContentDataProvider to use IBinding. - Added new ContentsDataProvider, ContentsArrayDataProvider, and DropDownDataProvider for flexible data extraction. - Updated DataBindings to use IDataProvider<T> properties instead of Binding. - Updated all usages to new interfaces and patterns.
This commit is contained in:
+2
-52
@@ -1,69 +1,19 @@
|
||||
|
||||
using aeqw89.DataKeys;
|
||||
using HtmlAgilityPack;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Beam.Dynamic {
|
||||
public class Binding(DataKey<Binding> key) : IKeyed<Binding> {
|
||||
public class Binding(DataKey<Binding> key) : IBinding, IKeyed<Binding> {
|
||||
public Binding(string key) : this(new DataKey<Binding>(key)) { }
|
||||
public Binding() : this("") { }
|
||||
|
||||
[JsonRequired]
|
||||
public DataKey<Binding> Key { get; set; } = key;
|
||||
[JsonRequired]
|
||||
public BindingType Type { get; set; }
|
||||
|
||||
public string? ArrayDelimiters { get; set; }
|
||||
public string? XPath { get; set; }
|
||||
public string? CssPath { get; set; }
|
||||
public string? Text { get; set; }
|
||||
private IDataProvider? Provider_;
|
||||
public IDataProvider? Provider {
|
||||
get => Provider_;
|
||||
set {
|
||||
if (value is null)
|
||||
return;
|
||||
if (value is not IDataProvider)
|
||||
throw new InvalidOperationException();
|
||||
var constructor = value.GetType().GetConstructor([]);
|
||||
if (!constructor?.IsPublic ?? true)
|
||||
throw new InvalidOperationException();
|
||||
Provider_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
public HtmlNode? ResolveNode(HtmlDocument doc) {
|
||||
if (XPath is not null)
|
||||
return doc.DocumentNode.SelectSingleNode(XPath);
|
||||
if (CssPath is not null)
|
||||
return doc.DocumentNode.ThenByClasses(CssPath.Split('/'));
|
||||
if (Provider is not null)
|
||||
return Provider.GetNode(doc);
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ResolveString(HtmlDocument doc) {
|
||||
if (XPath is not null)
|
||||
return doc.DocumentNode.SelectSingleNode(XPath)?.InnerText ?? "";
|
||||
if (CssPath is not null)
|
||||
return doc.DocumentNode.ThenByClasses(CssPath.Split('/'))?.InnerText ?? "";
|
||||
if (Provider is not null)
|
||||
return Provider.Get(doc);
|
||||
return "";
|
||||
}
|
||||
|
||||
public string[] ResolveArray(HtmlDocument doc) {
|
||||
if (Type is not BindingType.Array)
|
||||
return [];
|
||||
var str = ResolveString(doc);
|
||||
return str.Split(ArrayDelimiters);
|
||||
}
|
||||
|
||||
public dynamic? Resolve(HtmlDocument doc) => Type switch {
|
||||
BindingType.Single => ResolveString(doc),
|
||||
BindingType.Array => ResolveArray(doc),
|
||||
BindingType.UseProvider => Provider?.Get(doc),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user