Introduced PostBuildBehavior enum and BehaveOnPostBuild() method to configure behavior when modifying the service collection after the service provider is built. Replaced EnsureNotBuilt() with EnsureBuilt() to support configurable handling (throw exception or ignore). This improves flexibility in scenarios where post-build service modifications should be optionally allowed or silently ignored.
140 lines
3.6 KiB
C#
140 lines
3.6 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using System.Collections;
|
|
#if NETFRAMEWORK
|
|
using System;
|
|
using System.Collections.Generic;
|
|
#endif
|
|
|
|
namespace DigitalData.Core.Abstractions
|
|
{
|
|
public class Factory : IServiceProvider, IServiceCollection
|
|
{
|
|
public static readonly Factory Shared = new Factory();
|
|
|
|
private readonly IServiceCollection _serviceCollection = new ServiceCollection();
|
|
private readonly Lazy<IServiceProvider> _lazyServiceProvider;
|
|
|
|
private bool IsBuilt => _lazyServiceProvider.IsValueCreated;
|
|
|
|
private PostBuildBehavior _pbBehavior = PostBuildBehavior.ThrowException;
|
|
|
|
public Factory BehaveOnPostBuild(PostBuildBehavior postBuildBehavior)
|
|
{
|
|
_pbBehavior = postBuildBehavior;
|
|
return this;
|
|
}
|
|
|
|
public Factory()
|
|
{
|
|
_lazyServiceProvider = new Lazy<IServiceProvider>(() => _serviceCollection.BuildServiceProvider());
|
|
}
|
|
|
|
#region Service Provider
|
|
public object
|
|
#if NET
|
|
?
|
|
#endif
|
|
GetService(Type serviceType)
|
|
{
|
|
return _lazyServiceProvider.Value.GetService(serviceType);
|
|
}
|
|
#endregion
|
|
|
|
#region Service Collection
|
|
public int Count => _serviceCollection.Count;
|
|
|
|
public bool IsReadOnly => _serviceCollection.IsReadOnly;
|
|
|
|
public ServiceDescriptor this[int index]
|
|
{
|
|
get => _serviceCollection[index];
|
|
set
|
|
{
|
|
if (EnsureBuilt())
|
|
return;
|
|
_serviceCollection[index] = value;
|
|
}
|
|
}
|
|
|
|
public int IndexOf(ServiceDescriptor item)
|
|
{
|
|
return _serviceCollection.IndexOf(item);
|
|
}
|
|
|
|
public void Insert(int index, ServiceDescriptor item)
|
|
{
|
|
if (EnsureBuilt())
|
|
return;
|
|
_serviceCollection.Insert(index, item);
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
if (EnsureBuilt())
|
|
return;
|
|
_serviceCollection.RemoveAt(index);
|
|
}
|
|
|
|
public void Add(ServiceDescriptor item)
|
|
{
|
|
if (EnsureBuilt())
|
|
return;
|
|
_serviceCollection.Add(item);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
if (EnsureBuilt())
|
|
return;
|
|
_serviceCollection.Clear();
|
|
}
|
|
|
|
public bool Contains(ServiceDescriptor item)
|
|
{
|
|
return _serviceCollection.Contains(item);
|
|
}
|
|
|
|
public void CopyTo(ServiceDescriptor[] array, int arrayIndex)
|
|
{
|
|
_serviceCollection.CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
public bool Remove(ServiceDescriptor item)
|
|
{
|
|
if (EnsureBuilt())
|
|
return false;
|
|
return _serviceCollection.Remove(item);
|
|
}
|
|
|
|
public IEnumerator<ServiceDescriptor> GetEnumerator()
|
|
{
|
|
return _serviceCollection.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return (_serviceCollection as IEnumerable).GetEnumerator();
|
|
}
|
|
#endregion
|
|
|
|
#region Helpers
|
|
private bool EnsureBuilt()
|
|
{
|
|
if (IsBuilt)
|
|
{
|
|
return _pbBehavior == PostBuildBehavior.ThrowException
|
|
? throw new InvalidOperationException("Service provider has already been built. No further service modifications are allowed.")
|
|
: true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
public enum PostBuildBehavior
|
|
{
|
|
ThrowException,
|
|
Ignore
|
|
}
|
|
} |