From 8b1237e2c49f12997fa72541900f0933a74daf7b Mon Sep 17 00:00:00 2001 From: Kevin Hahn Date: Tue, 15 Oct 2024 10:05:33 +0700 Subject: [PATCH] allow multiple object adapters --- .../Adapters/CustomAdapterProvider.cs | 8 +++- .../Adapters/DefaultAdapterProvider.cs | 8 +++- .../Adapters/IObjectAdapterProvider.cs | 3 +- src/SIL.Harmony/CrdtConfig.cs | 41 +++++++++++++------ 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/SIL.Harmony/Adapters/CustomAdapterProvider.cs b/src/SIL.Harmony/Adapters/CustomAdapterProvider.cs index 53231cc..81a2252 100644 --- a/src/SIL.Harmony/Adapters/CustomAdapterProvider.cs +++ b/src/SIL.Harmony/Adapters/CustomAdapterProvider.cs @@ -12,8 +12,7 @@ public class CustomAdapterProvider : IObjectAd { private readonly ObjectTypeListBuilder _objectTypeListBuilder; private readonly List _objectTypes = new(); - private Dictionary> JsonTypes { get; } = []; - Dictionary> IObjectAdapterProvider.JsonTypes => JsonTypes; + private Dictionary> JsonTypes => _objectTypeListBuilder.JsonTypes; public CustomAdapterProvider(ObjectTypeListBuilder objectTypeListBuilder) { @@ -55,6 +54,11 @@ IObjectBase IObjectAdapterProvider.Adapt(object obj) { return TCustomAdapter.Create((TCommonInterface)obj); } + + public bool CanAdapt(object obj) + { + return obj is TCommonInterface; + } } // it's possible to implement this without a Common interface diff --git a/src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs b/src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs index 53bea0f..b764ba9 100644 --- a/src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs +++ b/src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs @@ -38,6 +38,10 @@ IObjectBase IObjectAdapterProvider.Adapt(object obj) $"Object is of type {obj.GetType().Name} which does not implement {nameof(IObjectBase)}"); } - private Dictionary> JsonTypes { get; } = []; - Dictionary> IObjectAdapterProvider.JsonTypes => JsonTypes; + public bool CanAdapt(object obj) + { + return obj is IObjectBase; + } + + private Dictionary> JsonTypes => objectTypeListBuilder.JsonTypes; } \ No newline at end of file diff --git a/src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs b/src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs index 6504c0a..98b21dd 100644 --- a/src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs +++ b/src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs @@ -11,6 +11,5 @@ internal interface IObjectAdapterProvider { IEnumerable GetRegistrations(); IObjectBase Adapt(object obj); - - Dictionary> JsonTypes { get; } + bool CanAdapt(object obj); } \ No newline at end of file diff --git a/src/SIL.Harmony/CrdtConfig.cs b/src/SIL.Harmony/CrdtConfig.cs index 1c24f12..da54811 100644 --- a/src/SIL.Harmony/CrdtConfig.cs +++ b/src/SIL.Harmony/CrdtConfig.cs @@ -75,12 +75,12 @@ public void AddRemoteResourceEntity(string? cachePath = null) { RemoteResourcesEnabled = true; LocalResourceCachePath = cachePath ?? LocalResourceCachePath; - ObjectTypeListBuilder.Add(); + ObjectTypeListBuilder.DefaultAdapter().Add(); ChangeTypeListBuilder.Add(); ChangeTypeListBuilder.Add(); ChangeTypeListBuilder.Add(); ChangeTypeListBuilder.Add>(); - ObjectTypeListBuilder.AddDbModelConfig(builder => + ObjectTypeListBuilder.ModelConfigurations.Add((builder, config) => { var entity = builder.Entity(); entity.HasKey(lr => lr.Id); @@ -127,8 +127,7 @@ public void Freeze() { if (_frozen) return; _frozen = true; - JsonTypes = AdapterProvider.JsonTypes; - foreach (var registration in AdapterProvider.GetRegistrations()) + foreach (var registration in AdapterProviders.SelectMany(a => a.GetRegistrations())) { ModelConfigurations.Add((builder, config) => { @@ -147,19 +146,18 @@ internal void CheckFrozen() if (_frozen) throw new InvalidOperationException($"{nameof(ObjectTypeListBuilder)} is frozen"); } - internal Dictionary>? JsonTypes { get; set; } + internal Dictionary> JsonTypes { get; } = []; internal List> ModelConfigurations { get; } = []; - internal IObjectAdapterProvider AdapterProvider => _adapterProvider ?? throw new InvalidOperationException("No adapter has been added to the builder"); - private IObjectAdapterProvider? _adapterProvider; + internal List AdapterProviders { get; } = []; public DefaultAdapterProvider DefaultAdapter() { CheckFrozen(); - if (_adapterProvider is not null) throw new InvalidOperationException("adapter has already been added"); - var adapter = new DefaultAdapterProvider(this); - _adapterProvider = adapter; + if (AdapterProviders.OfType().SingleOrDefault() is {} adapter) return adapter; + adapter = new DefaultAdapterProvider(this); + AdapterProviders.Add(adapter); return adapter; } @@ -182,9 +180,26 @@ public CustomAdapterProvider CustomAdapter, IPolyType { CheckFrozen(); - if (_adapterProvider is not null) throw new InvalidOperationException("adapter has already been added"); - var adapter = new CustomAdapterProvider(this); - _adapterProvider = adapter; + if (AdapterProviders.OfType>().SingleOrDefault() is {} adapter) return adapter; + adapter = new CustomAdapterProvider(this); + AdapterProviders.Add(adapter); return adapter; } + + internal IObjectBase Adapt(object obj) + { + if (AdapterProviders is [{ } defaultAdapter]) + { + return defaultAdapter.Adapt(obj); + } + + foreach (var objectAdapterProvider in AdapterProviders) + { + if (objectAdapterProvider.CanAdapt(obj)) + { + return objectAdapterProvider.Adapt(obj); + } + } + throw new ArgumentException($"Unable to adapt object of type {obj.GetType()}"); + } }