diff --git a/Unosquare.Swan/Abstractions/AppWorkerBase.cs b/Unosquare.Swan/Abstractions/AppWorkerBase.cs
index 583b626..a8239a9 100644
--- a/Unosquare.Swan/Abstractions/AppWorkerBase.cs
+++ b/Unosquare.Swan/Abstractions/AppWorkerBase.cs
@@ -1,214 +1,203 @@
-namespace Unosquare.Swan.Abstractions
-{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
-
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Unosquare.Swan.Abstractions {
+ ///
+ /// A base implementation of an Application service containing a worker task that performs background processing.
+ ///
+ ///
+ /// The following code describes how to implement the class.
+ ///
+ /// using System;
+ /// using System.Threading.Tasks;
+ /// using Unosquare.Swan;
+ /// using Unosquare.Swan.Abstractions;
+ ///
+ /// class Worker : AppWorkerBase
+ /// {
+ /// // an action that will be executed if the worker is stopped
+ /// public Action OnExit { get; set; }
+ ///
+ /// // override the base loop method, this is the code will
+ /// // execute until the cancellation token is canceled.
+ /// protected override Task WorkerThreadLoop()
+ /// {
+ /// // delay a second and then proceed
+ /// await Task.Delay(TimeSpan.FromMilliseconds(1000), CancellationToken);
+ ///
+ /// // just print out this
+ /// $"Working...".WriteLine();
+ /// }
+ ///
+ /// // Once the worker is stopped this code will be executed
+ /// protected override void OnWorkerThreadExit()
+ /// {
+ /// // execute the base method
+ /// base.OnWorkerThreadExit();
+ ///
+ /// // then if the OnExit Action is not null execute it
+ /// OnExit?.Invoke();
+ /// }
+ /// }
+ ///
+ ///
+ public abstract class AppWorkerBase
+ : IWorker, IDisposable {
+ private readonly Object _syncLock = new Object();
+ private AppWorkerState _workerState = AppWorkerState.Stopped;
+ private CancellationTokenSource _tokenSource;
+
///
- /// A base implementation of an Application service containing a worker task that performs background processing.
+ /// Initializes a new instance of the class.
///
- ///
- /// The following code describes how to implement the class.
- ///
- /// using System;
- /// using System.Threading.Tasks;
- /// using Unosquare.Swan;
- /// using Unosquare.Swan.Abstractions;
- ///
- /// class Worker : AppWorkerBase
- /// {
- /// // an action that will be executed if the worker is stopped
- /// public Action OnExit { get; set; }
- ///
- /// // override the base loop method, this is the code will
- /// // execute until the cancellation token is canceled.
- /// protected override Task WorkerThreadLoop()
- /// {
- /// // delay a second and then proceed
- /// await Task.Delay(TimeSpan.FromMilliseconds(1000), CancellationToken);
- ///
- /// // just print out this
- /// $"Working...".WriteLine();
- /// }
- ///
- /// // Once the worker is stopped this code will be executed
- /// protected override void OnWorkerThreadExit()
- /// {
- /// // execute the base method
- /// base.OnWorkerThreadExit();
- ///
- /// // then if the OnExit Action is not null execute it
- /// OnExit?.Invoke();
- /// }
- /// }
- ///
- ///
- public abstract class AppWorkerBase
- : IWorker, IDisposable
- {
- private readonly object _syncLock = new object();
- private AppWorkerState _workerState = AppWorkerState.Stopped;
- private CancellationTokenSource _tokenSource;
-
- ///
- /// Initializes a new instance of the class.
- ///
- protected AppWorkerBase()
- {
- State = AppWorkerState.Stopped;
- IsBusy = false;
- }
-
- ///
- /// Occurs when [state changed].
- ///
- public event EventHandler StateChanged;
-
- #region Properties
-
- ///
- /// Gets the state of the application service.
- /// In other words, useful to know whether the service is running.
- ///
- ///
- /// The state.
- ///
- public AppWorkerState State
- {
- get => _workerState;
-
- private set
- {
- lock (_syncLock)
- {
- if (value == _workerState) return;
-
- $"Service state changing from {State} to {value}".Debug(GetType().Name);
- var newState = value;
- var oldState = _workerState;
- _workerState = value;
-
- StateChanged?.Invoke(this, new AppWorkerStateChangedEventArgs(oldState, newState));
- }
- }
- }
-
- ///
- /// Gets the cancellation token.
- ///
- ///
- /// The cancellation token.
- ///
- public CancellationToken CancellationToken => _tokenSource?.Token ?? default;
-
- ///
- /// Gets a value indicating whether the thread is busy.
- ///
- ///
- /// true if this instance is busy; otherwise, false.
- ///
- public bool IsBusy { get; private set; }
-
- #endregion
-
- #region AppWorkerBase Methods
-
- ///
- /// Performs internal service initialization tasks required before starting the service.
- ///
- /// Service cannot be initialized because it seems to be currently running.
- public virtual void Initialize() => CheckIsRunning();
-
- ///
- /// Service cannot be started because it seems to be currently running.
- public virtual void Start()
- {
- CheckIsRunning();
-
- CreateWorker();
- State = AppWorkerState.Running;
- }
-
- ///
- /// Service cannot be stopped because it is not running.
- public virtual void Stop()
- {
- if (State != AppWorkerState.Running)
- return;
-
- _tokenSource?.Cancel();
- "Service stop requested.".Debug(GetType().Name);
- State = AppWorkerState.Stopped;
- }
-
- ///
- public void Dispose() => _tokenSource?.Dispose();
-
- #endregion
-
- #region Abstract and Virtual Methods
-
- ///
- /// Called when an unhandled exception is thrown.
- ///
- /// The ex.
- protected virtual void OnWorkerThreadLoopException(Exception ex)
- => "Service exception detected.".Debug(GetType().Name, ex);
-
- ///
- /// This method is called when the user loop has exited.
- ///
- protected virtual void OnWorkerThreadExit() => "Service thread is stopping.".Debug(GetType().Name);
-
- ///
- /// Implement this method as a loop that checks whether CancellationPending has been set to true
- /// If so, immediately exit the loop.
- ///
- /// A task representing the execution of the worker.
- protected abstract Task WorkerThreadLoop();
-
- private void CheckIsRunning()
- {
- if (State != AppWorkerState.Stopped)
- throw new InvalidOperationException("Service cannot be initialized because it seems to be currently running.");
- }
-
- private void CreateWorker()
- {
- _tokenSource = new CancellationTokenSource();
- _tokenSource.Token.Register(() =>
- {
- IsBusy = false;
- OnWorkerThreadExit();
- });
-
- Task.Run(async () =>
- {
- IsBusy = true;
-
- try
- {
- while (!CancellationToken.IsCancellationRequested)
- {
- await WorkerThreadLoop().ConfigureAwait(false);
- }
- }
- catch (AggregateException)
- {
- // Ignored
- }
- catch (Exception ex)
- {
- ex.Log(GetType().Name);
- OnWorkerThreadLoopException(ex);
-
- if (!_tokenSource.IsCancellationRequested)
- _tokenSource.Cancel();
- }
- },
- _tokenSource.Token);
- }
-
- #endregion
- }
+ protected AppWorkerBase() {
+ this.State = AppWorkerState.Stopped;
+ this.IsBusy = false;
+ }
+
+ ///
+ /// Occurs when [state changed].
+ ///
+ public event EventHandler StateChanged;
+
+ #region Properties
+
+ ///
+ /// Gets the state of the application service.
+ /// In other words, useful to know whether the service is running.
+ ///
+ ///
+ /// The state.
+ ///
+ public AppWorkerState State {
+ get => this._workerState;
+
+ private set {
+ lock(this._syncLock) {
+ if(value == this._workerState) {
+ return;
+ }
+
+ $"Service state changing from {this.State} to {value}".Debug(this.GetType().Name);
+ AppWorkerState newState = value;
+ AppWorkerState oldState = this._workerState;
+ this._workerState = value;
+
+ StateChanged?.Invoke(this, new AppWorkerStateChangedEventArgs(oldState, newState));
+ }
+ }
+ }
+
+ ///
+ /// Gets the cancellation token.
+ ///
+ ///
+ /// The cancellation token.
+ ///
+ public CancellationToken CancellationToken => this._tokenSource?.Token ?? default;
+
+ ///
+ /// Gets a value indicating whether the thread is busy.
+ ///
+ ///
+ /// true if this instance is busy; otherwise, false.
+ ///
+ public Boolean IsBusy {
+ get; private set;
+ }
+
+ #endregion
+
+ #region AppWorkerBase Methods
+
+ ///
+ /// Performs internal service initialization tasks required before starting the service.
+ ///
+ /// Service cannot be initialized because it seems to be currently running.
+ public virtual void Initialize() => this.CheckIsRunning();
+
+ ///
+ /// Service cannot be started because it seems to be currently running.
+ public virtual void Start() {
+ this.CheckIsRunning();
+
+ this.CreateWorker();
+ this.State = AppWorkerState.Running;
+ }
+
+ ///
+ /// Service cannot be stopped because it is not running.
+ public virtual void Stop() {
+ if(this.State != AppWorkerState.Running) {
+ return;
+ }
+
+ this._tokenSource?.Cancel();
+ "Service stop requested.".Debug(this.GetType().Name);
+ this.State = AppWorkerState.Stopped;
+ }
+
+ ///
+ public void Dispose() => this._tokenSource?.Dispose();
+
+ #endregion
+
+ #region Abstract and Virtual Methods
+
+ ///
+ /// Called when an unhandled exception is thrown.
+ ///
+ /// The ex.
+ protected virtual void OnWorkerThreadLoopException(Exception ex)
+ => "Service exception detected.".Debug(this.GetType().Name, ex);
+
+ ///
+ /// This method is called when the user loop has exited.
+ ///
+ protected virtual void OnWorkerThreadExit() => "Service thread is stopping.".Debug(this.GetType().Name);
+
+ ///
+ /// Implement this method as a loop that checks whether CancellationPending has been set to true
+ /// If so, immediately exit the loop.
+ ///
+ /// A task representing the execution of the worker.
+ protected abstract Task WorkerThreadLoop();
+
+ private void CheckIsRunning() {
+ if(this.State != AppWorkerState.Stopped) {
+ throw new InvalidOperationException("Service cannot be initialized because it seems to be currently running.");
+ }
+ }
+
+ private void CreateWorker() {
+ this._tokenSource = new CancellationTokenSource();
+ _ = this._tokenSource.Token.Register(() => {
+ this.IsBusy = false;
+ this.OnWorkerThreadExit();
+ });
+
+ _ = Task.Run(async () => {
+ this.IsBusy = true;
+
+ try {
+ while(!this.CancellationToken.IsCancellationRequested) {
+ await this.WorkerThreadLoop().ConfigureAwait(false);
+ }
+ } catch(AggregateException) {
+ // Ignored
+ } catch(Exception ex) {
+ ex.Log(this.GetType().Name);
+ this.OnWorkerThreadLoopException(ex);
+
+ if(!this._tokenSource.IsCancellationRequested) {
+ this._tokenSource.Cancel();
+ }
+ }
+ },
+ this._tokenSource.Token);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.Swan/Abstractions/AppWorkerStateChangedEventArgs.cs b/Unosquare.Swan/Abstractions/AppWorkerStateChangedEventArgs.cs
index a34e6fe..485475e 100644
--- a/Unosquare.Swan/Abstractions/AppWorkerStateChangedEventArgs.cs
+++ b/Unosquare.Swan/Abstractions/AppWorkerStateChangedEventArgs.cs
@@ -1,37 +1,38 @@
-namespace Unosquare.Swan.Abstractions
-{
- using System;
-
+using System;
+
+namespace Unosquare.Swan.Abstractions {
+ ///
+ /// Represents event arguments whenever the state of an application service changes.
+ ///
+ public class AppWorkerStateChangedEventArgs : EventArgs {
///
- /// Represents event arguments whenever the state of an application service changes.
+ /// Initializes a new instance of the class.
///
- public class AppWorkerStateChangedEventArgs : EventArgs
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The old state.
- /// The new state.
- public AppWorkerStateChangedEventArgs(AppWorkerState oldState, AppWorkerState newState)
- {
- OldState = oldState;
- NewState = newState;
- }
-
- ///
- /// Gets the state to which the application service changed.
- ///
- ///
- /// The new state.
- ///
- public AppWorkerState NewState { get; }
-
- ///
- /// Gets the old state.
- ///
- ///
- /// The old state.
- ///
- public AppWorkerState OldState { get; }
- }
+ /// The old state.
+ /// The new state.
+ public AppWorkerStateChangedEventArgs(AppWorkerState oldState, AppWorkerState newState) {
+ this.OldState = oldState;
+ this.NewState = newState;
+ }
+
+ ///
+ /// Gets the state to which the application service changed.
+ ///
+ ///
+ /// The new state.
+ ///
+ public AppWorkerState NewState {
+ get;
+ }
+
+ ///
+ /// Gets the old state.
+ ///
+ ///
+ /// The old state.
+ ///
+ public AppWorkerState OldState {
+ get;
+ }
+ }
}
diff --git a/Unosquare.Swan/Components/CircularBuffer.cs b/Unosquare.Swan/Components/CircularBuffer.cs
index c8cf6db..3aed66c 100644
--- a/Unosquare.Swan/Components/CircularBuffer.cs
+++ b/Unosquare.Swan/Components/CircularBuffer.cs
@@ -1,204 +1,202 @@
-namespace Unosquare.Swan.Components
-{
- using System;
- using System.Runtime.InteropServices;
-
+using System;
+using System.Runtime.InteropServices;
+
+namespace Unosquare.Swan.Components {
+ ///
+ /// A fixed-size buffer that acts as an infinite length one.
+ /// This buffer is backed by unmanaged, very fast memory so ensure you call
+ /// the dispose method when you are done using it.
+ /// Only for Windows.
+ ///
+ ///
+ public sealed class CircularBuffer : IDisposable {
+ private readonly Object _syncLock = new Object();
+ private IntPtr _buffer = IntPtr.Zero;
+
///
- /// A fixed-size buffer that acts as an infinite length one.
- /// This buffer is backed by unmanaged, very fast memory so ensure you call
- /// the dispose method when you are done using it.
- /// Only for Windows.
+ /// Initializes a new instance of the class.
///
- ///
- public sealed class CircularBuffer : IDisposable
- {
- private readonly object _syncLock = new object();
- private IntPtr _buffer = IntPtr.Zero;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Length of the buffer.
- public CircularBuffer(int bufferLength)
- {
+ /// Length of the buffer.
+ public CircularBuffer(Int32 bufferLength) {
#if !NET452
if (Runtime.OS != Swan.OperatingSystem.Windows)
throw new InvalidOperationException("CircularBuffer component is only available in Windows");
#endif
-
- Length = bufferLength;
- _buffer = Marshal.AllocHGlobal(Length);
- }
-
- #region Properties
-
- ///
- /// Gets the capacity of this buffer.
- ///
- ///
- /// The length.
- ///
- public int Length { get; private set; }
-
- ///
- /// Gets the current, 0-based read index.
- ///
- ///
- /// The index of the read.
- ///
- public int ReadIndex { get; private set; }
-
- ///
- /// Gets the current, 0-based write index.
- ///
- ///
- /// The index of the write.
- ///
- public int WriteIndex { get; private set; }
-
- ///
- /// Gets an the object associated with the last write.
- ///
- ///
- /// The write tag.
- ///
- public TimeSpan WriteTag { get; private set; } = TimeSpan.MinValue;
-
- ///
- /// Gets the available bytes to read.
- ///
- ///
- /// The readable count.
- ///
- public int ReadableCount { get; private set; }
-
- ///
- /// Gets the number of bytes that can be written.
- ///
- ///
- /// The writable count.
- ///
- public int WritableCount => Length - ReadableCount;
-
- ///
- /// Gets percentage of used bytes (readbale/available, from 0.0 to 1.0).
- ///
- ///
- /// The capacity percent.
- ///
- public double CapacityPercent => 1.0 * ReadableCount / Length;
-
- #endregion
-
- #region Methods
-
- ///
- /// Reads the specified number of bytes into the target array.
- ///
- /// The requested bytes.
- /// The target.
- /// The target offset.
- ///
- /// Exception that is thrown when a method call is invalid for the object's current state.
- ///
- public void Read(int requestedBytes, byte[] target, int targetOffset)
- {
- lock (_syncLock)
- {
- if (requestedBytes > ReadableCount)
- {
- throw new InvalidOperationException(
- $"Unable to read {requestedBytes} bytes. Only {ReadableCount} bytes are available");
- }
-
- var readCount = 0;
- while (readCount < requestedBytes)
- {
- var copyLength = Math.Min(Length - ReadIndex, requestedBytes - readCount);
- var sourcePtr = _buffer + ReadIndex;
- Marshal.Copy(sourcePtr, target, targetOffset + readCount, copyLength);
-
- readCount += copyLength;
- ReadIndex += copyLength;
- ReadableCount -= copyLength;
-
- if (ReadIndex >= Length)
- ReadIndex = 0;
- }
- }
- }
-
- ///
- /// Writes data to the backing buffer using the specified pointer and length.
- /// and associating a write tag for this operation.
- ///
- /// The source.
- /// The length.
- /// The write tag.
- /// Unable to write to circular buffer. Call the Read method to make some additional room.
- public void Write(IntPtr source, int length, TimeSpan writeTag)
- {
- lock (_syncLock)
- {
- if (ReadableCount + length > Length)
- {
- throw new InvalidOperationException(
- $"Unable to write to circular buffer. Call the {nameof(Read)} method to make some additional room.");
- }
-
- var writeCount = 0;
- while (writeCount < length)
- {
- var copyLength = Math.Min(Length - WriteIndex, length - writeCount);
- var sourcePtr = source + writeCount;
- var targetPtr = _buffer + WriteIndex;
- CopyMemory(targetPtr, sourcePtr, (uint) copyLength);
-
- writeCount += copyLength;
- WriteIndex += copyLength;
- ReadableCount += copyLength;
-
- if (WriteIndex >= Length)
- WriteIndex = 0;
- }
-
- WriteTag = writeTag;
- }
- }
-
- ///
- /// Resets all states as if this buffer had just been created.
- ///
- public void Clear()
- {
- lock (_syncLock)
- {
- WriteIndex = 0;
- ReadIndex = 0;
- WriteTag = TimeSpan.MinValue;
- ReadableCount = 0;
- }
- }
-
- ///
- public void Dispose()
- {
- if (_buffer == IntPtr.Zero) return;
-
- Marshal.FreeHGlobal(_buffer);
- _buffer = IntPtr.Zero;
- Length = 0;
- }
-
- ///
- /// Fast pointer memory block copy function.
- ///
- /// The destination.
- /// The source.
- /// The length.
- [DllImport("kernel32")]
- public static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
-
- #endregion
- }
+
+ this.Length = bufferLength;
+ this._buffer = Marshal.AllocHGlobal(this.Length);
+ }
+
+ #region Properties
+
+ ///
+ /// Gets the capacity of this buffer.
+ ///
+ ///
+ /// The length.
+ ///
+ public Int32 Length {
+ get; private set;
+ }
+
+ ///
+ /// Gets the current, 0-based read index.
+ ///
+ ///
+ /// The index of the read.
+ ///
+ public Int32 ReadIndex {
+ get; private set;
+ }
+
+ ///
+ /// Gets the current, 0-based write index.
+ ///
+ ///
+ /// The index of the write.
+ ///
+ public Int32 WriteIndex {
+ get; private set;
+ }
+
+ ///
+ /// Gets an the object associated with the last write.
+ ///
+ ///
+ /// The write tag.
+ ///
+ public TimeSpan WriteTag { get; private set; } = TimeSpan.MinValue;
+
+ ///
+ /// Gets the available bytes to read.
+ ///
+ ///
+ /// The readable count.
+ ///
+ public Int32 ReadableCount {
+ get; private set;
+ }
+
+ ///
+ /// Gets the number of bytes that can be written.
+ ///
+ ///
+ /// The writable count.
+ ///
+ public Int32 WritableCount => this.Length - this.ReadableCount;
+
+ ///
+ /// Gets percentage of used bytes (readbale/available, from 0.0 to 1.0).
+ ///
+ ///
+ /// The capacity percent.
+ ///
+ public Double CapacityPercent => 1.0 * this.ReadableCount / this.Length;
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Reads the specified number of bytes into the target array.
+ ///
+ /// The requested bytes.
+ /// The target.
+ /// The target offset.
+ ///
+ /// Exception that is thrown when a method call is invalid for the object's current state.
+ ///
+ public void Read(Int32 requestedBytes, Byte[] target, Int32 targetOffset) {
+ lock(this._syncLock) {
+ if(requestedBytes > this.ReadableCount) {
+ throw new InvalidOperationException(
+ $"Unable to read {requestedBytes} bytes. Only {this.ReadableCount} bytes are available");
+ }
+
+ Int32 readCount = 0;
+ while(readCount < requestedBytes) {
+ Int32 copyLength = Math.Min(this.Length - this.ReadIndex, requestedBytes - readCount);
+ IntPtr sourcePtr = this._buffer + this.ReadIndex;
+ Marshal.Copy(sourcePtr, target, targetOffset + readCount, copyLength);
+
+ readCount += copyLength;
+ this.ReadIndex += copyLength;
+ this.ReadableCount -= copyLength;
+
+ if(this.ReadIndex >= this.Length) {
+ this.ReadIndex = 0;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Writes data to the backing buffer using the specified pointer and length.
+ /// and associating a write tag for this operation.
+ ///
+ /// The source.
+ /// The length.
+ /// The write tag.
+ /// Unable to write to circular buffer. Call the Read method to make some additional room.
+ public void Write(IntPtr source, Int32 length, TimeSpan writeTag) {
+ lock(this._syncLock) {
+ if(this.ReadableCount + length > this.Length) {
+ throw new InvalidOperationException(
+ $"Unable to write to circular buffer. Call the {nameof(Read)} method to make some additional room.");
+ }
+
+ Int32 writeCount = 0;
+ while(writeCount < length) {
+ Int32 copyLength = Math.Min(this.Length - this.WriteIndex, length - writeCount);
+ IntPtr sourcePtr = source + writeCount;
+ IntPtr targetPtr = this._buffer + this.WriteIndex;
+ CopyMemory(targetPtr, sourcePtr, (UInt32)copyLength);
+
+ writeCount += copyLength;
+ this.WriteIndex += copyLength;
+ this.ReadableCount += copyLength;
+
+ if(this.WriteIndex >= this.Length) {
+ this.WriteIndex = 0;
+ }
+ }
+
+ this.WriteTag = writeTag;
+ }
+ }
+
+ ///
+ /// Resets all states as if this buffer had just been created.
+ ///
+ public void Clear() {
+ lock(this._syncLock) {
+ this.WriteIndex = 0;
+ this.ReadIndex = 0;
+ this.WriteTag = TimeSpan.MinValue;
+ this.ReadableCount = 0;
+ }
+ }
+
+ ///
+ public void Dispose() {
+ if(this._buffer == IntPtr.Zero) {
+ return;
+ }
+
+ Marshal.FreeHGlobal(this._buffer);
+ this._buffer = IntPtr.Zero;
+ this.Length = 0;
+ }
+
+ ///
+ /// Fast pointer memory block copy function.
+ ///
+ /// The destination.
+ /// The source.
+ /// The length.
+ [DllImport("kernel32")]
+ public static extern void CopyMemory(IntPtr destination, IntPtr source, UInt32 length);
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.Swan/Components/CsProjFile.cs b/Unosquare.Swan/Components/CsProjFile.cs
index 12b05db..39358c5 100644
--- a/Unosquare.Swan/Components/CsProjFile.cs
+++ b/Unosquare.Swan/Components/CsProjFile.cs
@@ -1,109 +1,101 @@
-namespace Unosquare.Swan.Components
-{
- using System;
- using System.IO;
- using System.Linq;
- using System.Xml.Linq;
-
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml.Linq;
+
+namespace Unosquare.Swan.Components {
+ ///
+ /// Represents a CsProjFile (and FsProjFile) parser.
+ ///
+ ///
+ /// Based on https://github.com/maartenba/dotnetcli-init.
+ ///
+ /// The type of CsProjMetadataBase.
+ ///
+ public class CsProjFile
+ : IDisposable
+ where T : CsProjMetadataBase {
+ private readonly Stream _stream;
+ private readonly Boolean _leaveOpen;
+ private readonly XDocument _xmlDocument;
+
///
- /// Represents a CsProjFile (and FsProjFile) parser.
+ /// Initializes a new instance of the class.
///
- ///
- /// Based on https://github.com/maartenba/dotnetcli-init.
- ///
- /// The type of CsProjMetadataBase.
- ///
- public class CsProjFile
- : IDisposable
- where T : CsProjMetadataBase
- {
- private readonly Stream _stream;
- private readonly bool _leaveOpen;
- private readonly XDocument _xmlDocument;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The filename.
- public CsProjFile(string filename = null)
- : this(OpenFile(filename))
- {
- // placeholder
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The stream.
- /// if set to true [leave open].
- /// Project file is not of the new .csproj type.
- public CsProjFile(Stream stream, bool leaveOpen = false)
- {
- _stream = stream;
- _leaveOpen = leaveOpen;
-
- _xmlDocument = XDocument.Load(stream);
-
- var projectElement = _xmlDocument.Descendants("Project").FirstOrDefault();
- var sdkAttribute = projectElement?.Attribute("Sdk");
- var sdk = sdkAttribute?.Value;
- if (sdk != "Microsoft.NET.Sdk" && sdk != "Microsoft.NET.Sdk.Web")
- {
- throw new ArgumentException("Project file is not of the new .csproj type.");
- }
-
- Metadata = Activator.CreateInstance();
- Metadata.SetData(_xmlDocument);
- }
-
- ///
- /// Gets the metadata.
- ///
- ///
- /// The nu get metadata.
- ///
- public T Metadata { get; }
-
- ///
- /// Saves this instance.
- ///
- public void Save()
- {
- _stream.SetLength(0);
- _stream.Position = 0;
-
- _xmlDocument.Save(_stream);
- }
-
- ///
- public void Dispose()
- {
- if (!_leaveOpen)
- {
- _stream?.Dispose();
- }
- }
-
- private static FileStream OpenFile(string filename)
- {
- if (filename == null)
- {
- filename = Directory
- .EnumerateFiles(Directory.GetCurrentDirectory(), "*.csproj", SearchOption.TopDirectoryOnly)
- .FirstOrDefault();
- }
-
- if (filename == null)
- {
- filename = Directory
- .EnumerateFiles(Directory.GetCurrentDirectory(), "*.fsproj", SearchOption.TopDirectoryOnly)
- .FirstOrDefault();
- }
-
- if (string.IsNullOrWhiteSpace(filename))
- throw new ArgumentNullException(nameof(filename));
-
- return File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
- }
- }
+ /// The filename.
+ public CsProjFile(String filename = null)
+ : this(OpenFile(filename)) {
+ // placeholder
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// if set to true [leave open].
+ /// Project file is not of the new .csproj type.
+ public CsProjFile(Stream stream, Boolean leaveOpen = false) {
+ this._stream = stream;
+ this._leaveOpen = leaveOpen;
+
+ this._xmlDocument = XDocument.Load(stream);
+
+ XElement projectElement = this._xmlDocument.Descendants("Project").FirstOrDefault();
+ XAttribute sdkAttribute = projectElement?.Attribute("Sdk");
+ String sdk = sdkAttribute?.Value;
+ if(sdk != "Microsoft.NET.Sdk" && sdk != "Microsoft.NET.Sdk.Web") {
+ throw new ArgumentException("Project file is not of the new .csproj type.");
+ }
+
+ this.Metadata = Activator.CreateInstance();
+ this.Metadata.SetData(this._xmlDocument);
+ }
+
+ ///
+ /// Gets the metadata.
+ ///
+ ///
+ /// The nu get metadata.
+ ///
+ public T Metadata {
+ get;
+ }
+
+ ///
+ /// Saves this instance.
+ ///
+ public void Save() {
+ this._stream.SetLength(0);
+ this._stream.Position = 0;
+
+ this._xmlDocument.Save(this._stream);
+ }
+
+ ///
+ public void Dispose() {
+ if(!this._leaveOpen) {
+ this._stream?.Dispose();
+ }
+ }
+
+ private static FileStream OpenFile(String filename) {
+ if(filename == null) {
+ filename = Directory
+ .EnumerateFiles(Directory.GetCurrentDirectory(), "*.csproj", SearchOption.TopDirectoryOnly)
+ .FirstOrDefault();
+ }
+
+ if(filename == null) {
+ filename = Directory
+ .EnumerateFiles(Directory.GetCurrentDirectory(), "*.fsproj", SearchOption.TopDirectoryOnly)
+ .FirstOrDefault();
+ }
+
+ if(String.IsNullOrWhiteSpace(filename)) {
+ throw new ArgumentNullException(nameof(filename));
+ }
+
+ return File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
+ }
+ }
}
\ No newline at end of file
diff --git a/Unosquare.Swan/Components/CsProjMetadataBase.cs b/Unosquare.Swan/Components/CsProjMetadataBase.cs
index d4085c4..ee939d1 100644
--- a/Unosquare.Swan/Components/CsProjMetadataBase.cs
+++ b/Unosquare.Swan/Components/CsProjMetadataBase.cs
@@ -1,8 +1,9 @@
-namespace Unosquare.Swan.Components
+using System;
+using System.Linq;
+using System.Xml.Linq;
+
+namespace Unosquare.Swan.Components
{
- using System.Linq;
- using System.Xml.Linq;
-
///
/// Represents a CsProj metadata abstract class
/// to use with CsProjFile parser.
@@ -17,7 +18,7 @@
///
/// The package identifier.
///
- public string PackageId => FindElement(nameof(PackageId))?.Value;
+ public String PackageId => this.FindElement(nameof(this.PackageId))?.Value;
///
/// Gets the name of the assembly.
@@ -25,7 +26,7 @@
///
/// The name of the assembly.
///
- public string AssemblyName => FindElement(nameof(AssemblyName))?.Value;
+ public String AssemblyName => this.FindElement(nameof(this.AssemblyName))?.Value;
///
/// Gets the target frameworks.
@@ -33,7 +34,7 @@
///
/// The target frameworks.
///
- public string TargetFrameworks => FindElement(nameof(TargetFrameworks))?.Value;
+ public String TargetFrameworks => this.FindElement(nameof(this.TargetFrameworks))?.Value;
///
/// Gets the target framework.
@@ -41,7 +42,7 @@
///
/// The target framework.
///
- public string TargetFramework => FindElement(nameof(TargetFramework))?.Value;
+ public String TargetFramework => this.FindElement(nameof(this.TargetFramework))?.Value;
///
/// Gets the version.
@@ -49,25 +50,25 @@
///
/// The version.
///
- public string Version => FindElement(nameof(Version))?.Value;
+ public String Version => this.FindElement(nameof(this.Version))?.Value;
///
/// Parses the cs proj tags.
///
/// The arguments.
- public abstract void ParseCsProjTags(ref string[] args);
+ public abstract void ParseCsProjTags(ref String[] args);
///
/// Sets the data.
///
/// The XML document.
- public void SetData(XDocument xmlDocument) => _xmlDocument = xmlDocument;
+ public void SetData(XDocument xmlDocument) => this._xmlDocument = xmlDocument;
///
/// Finds the element.
///
/// Name of the element.
/// A XElement.
- protected XElement FindElement(string elementName) => _xmlDocument.Descendants(elementName).FirstOrDefault();
+ protected XElement FindElement(String elementName) => this._xmlDocument.Descendants(elementName).FirstOrDefault();
}
}
\ No newline at end of file
diff --git a/Unosquare.Swan/Components/DelayProvider.cs b/Unosquare.Swan/Components/DelayProvider.cs
index 51a3a24..a1cc03c 100644
--- a/Unosquare.Swan/Components/DelayProvider.cs
+++ b/Unosquare.Swan/Components/DelayProvider.cs
@@ -1,144 +1,139 @@
-namespace Unosquare.Swan.Components
-{
- using System;
- using System.Diagnostics;
- using System.Threading;
- using System.Threading.Tasks;
- using Abstractions;
-
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using Unosquare.Swan.Abstractions;
+
+namespace Unosquare.Swan.Components {
+ ///
+ /// Represents logic providing several delay mechanisms.
+ ///
+ ///
+ /// The following example shows how to implement delay mechanisms.
+ ///
+ /// using Unosquare.Swan.Components;
+ ///
+ /// public class Example
+ /// {
+ /// public static void Main()
+ /// {
+ /// // using the ThreadSleep strategy
+ /// using (var delay = new DelayProvider(DelayProvider.DelayStrategy.ThreadSleep))
+ /// {
+ /// // retrieve how much time was delayed
+ /// var time = delay.WaitOne();
+ /// }
+ /// }
+ /// }
+ ///
+ ///
+ public sealed class DelayProvider : IDisposable {
+ private readonly Object _syncRoot = new Object();
+ private readonly Stopwatch _delayStopwatch = new Stopwatch();
+
+ private Boolean _isDisposed;
+ private IWaitEvent _delayEvent;
+
///
- /// Represents logic providing several delay mechanisms.
+ /// Initializes a new instance of the class.
///
- ///
- /// The following example shows how to implement delay mechanisms.
- ///
- /// using Unosquare.Swan.Components;
- ///
- /// public class Example
- /// {
- /// public static void Main()
- /// {
- /// // using the ThreadSleep strategy
- /// using (var delay = new DelayProvider(DelayProvider.DelayStrategy.ThreadSleep))
- /// {
- /// // retrieve how much time was delayed
- /// var time = delay.WaitOne();
- /// }
- /// }
- /// }
- ///
- ///
- public sealed class DelayProvider : IDisposable
- {
- private readonly object _syncRoot = new object();
- private readonly Stopwatch _delayStopwatch = new Stopwatch();
-
- private bool _isDisposed;
- private IWaitEvent _delayEvent;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The strategy.
- public DelayProvider(DelayStrategy strategy = DelayStrategy.TaskDelay)
- {
- Strategy = strategy;
- }
-
- ///
- /// Enumerates the different ways of providing delays.
- ///
- public enum DelayStrategy
- {
- ///
- /// Using the Thread.Sleep(15) mechanism.
- ///
- ThreadSleep,
-
- ///
- /// Using the Task.Delay(1).Wait mechanism.
- ///
- TaskDelay,
-
- ///
- /// Using a wait event that completes in a background ThreadPool thread.
- ///
- ThreadPool,
- }
-
- ///
- /// Gets the selected delay strategy.
- ///
- public DelayStrategy Strategy { get; }
-
- ///
- /// Creates the smallest possible, synchronous delay based on the selected strategy.
- ///
- /// The elapsed time of the delay.
- public TimeSpan WaitOne()
- {
- lock (_syncRoot)
- {
- if (_isDisposed) return TimeSpan.Zero;
-
- _delayStopwatch.Restart();
-
- switch (Strategy)
- {
- case DelayStrategy.ThreadSleep:
- DelaySleep();
- break;
- case DelayStrategy.TaskDelay:
- DelayTask();
- break;
-#if !NETSTANDARD1_3
- case DelayStrategy.ThreadPool:
- DelayThreadPool();
- break;
+ /// The strategy.
+ public DelayProvider(DelayStrategy strategy = DelayStrategy.TaskDelay) => this.Strategy = strategy;
+
+ ///
+ /// Enumerates the different ways of providing delays.
+ ///
+ public enum DelayStrategy {
+ ///
+ /// Using the Thread.Sleep(15) mechanism.
+ ///
+ ThreadSleep,
+
+ ///
+ /// Using the Task.Delay(1).Wait mechanism.
+ ///
+ TaskDelay,
+
+ ///
+ /// Using a wait event that completes in a background ThreadPool thread.
+ ///
+ ThreadPool,
+ }
+
+ ///
+ /// Gets the selected delay strategy.
+ ///
+ public DelayStrategy Strategy {
+ get;
+ }
+
+ ///
+ /// Creates the smallest possible, synchronous delay based on the selected strategy.
+ ///
+ /// The elapsed time of the delay.
+ public TimeSpan WaitOne() {
+ lock(this._syncRoot) {
+ if(this._isDisposed) {
+ return TimeSpan.Zero;
+ }
+
+ this._delayStopwatch.Restart();
+
+ switch(this.Strategy) {
+ case DelayStrategy.ThreadSleep:
+ DelaySleep();
+ break;
+ case DelayStrategy.TaskDelay:
+ DelayTask();
+ break;
+#if !NETSTANDARD1_3
+ case DelayStrategy.ThreadPool:
+ this.DelayThreadPool();
+ break;
#endif
- }
-
- return _delayStopwatch.Elapsed;
- }
- }
-
- #region Dispose Pattern
-
- ///
- public void Dispose()
- {
- lock (_syncRoot)
- {
- if (_isDisposed) return;
- _isDisposed = true;
- _delayEvent?.Dispose();
- }
- }
-
- #endregion
-
- #region Private Delay Mechanisms
-
- private static void DelaySleep() => Thread.Sleep(15);
-
- private static void DelayTask() => Task.Delay(1).Wait();
-
-#if !NETSTANDARD1_3
- private void DelayThreadPool()
- {
- if (_delayEvent == null)
- _delayEvent = WaitEventFactory.Create(isCompleted: true, useSlim: true);
-
- _delayEvent.Begin();
- ThreadPool.QueueUserWorkItem((s) =>
- {
- DelaySleep();
- _delayEvent.Complete();
- });
-
- _delayEvent.Wait();
- }
+ }
+
+ return this._delayStopwatch.Elapsed;
+ }
+ }
+
+ #region Dispose Pattern
+
+ ///
+ public void Dispose() {
+ lock(this._syncRoot) {
+ if(this._isDisposed) {
+ return;
+ }
+
+ this._isDisposed = true;
+ this._delayEvent?.Dispose();
+ }
+ }
+
+ #endregion
+
+ #region Private Delay Mechanisms
+
+ private static void DelaySleep() => Thread.Sleep(15);
+
+ private static void DelayTask() => Task.Delay(1).Wait();
+
+#if !NETSTANDARD1_3
+ private void DelayThreadPool() {
+ if(this._delayEvent == null) {
+ this._delayEvent = WaitEventFactory.Create(isCompleted: true, useSlim: true);
+ }
+
+ this._delayEvent.Begin();
+ _ = ThreadPool.QueueUserWorkItem((s) => {
+ DelaySleep();
+ this._delayEvent.Complete();
+ });
+
+ this._delayEvent.Wait();
+ }
#endif
- #endregion
- }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Unosquare.Swan/Components/DependencyContainer.cs b/Unosquare.Swan/Components/DependencyContainer.cs
index f7d0ee7..5d87ced 100644
--- a/Unosquare.Swan/Components/DependencyContainer.cs
+++ b/Unosquare.Swan/Components/DependencyContainer.cs
@@ -1,715 +1,638 @@
-namespace Unosquare.Swan.Components
-{
- using Exceptions;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
-
+using Unosquare.Swan.Exceptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Unosquare.Swan.Components {
+ ///
+ /// The concrete implementation of a simple IoC container
+ /// based largely on TinyIoC (https://github.com/grumpydev/TinyIoC).
+ ///
+ ///
+ public partial class DependencyContainer : IDisposable {
+ private readonly Object _autoRegisterLock = new Object();
+
+ private Boolean _disposed;
+
+ static DependencyContainer() {
+ }
+
///
- /// The concrete implementation of a simple IoC container
- /// based largely on TinyIoC (https://github.com/grumpydev/TinyIoC).
+ /// Initializes a new instance of the class.
///
- ///
- public partial class DependencyContainer : IDisposable
- {
- private readonly object _autoRegisterLock = new object();
-
- private bool _disposed;
-
- static DependencyContainer()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public DependencyContainer()
- {
- RegisteredTypes = new TypesConcurrentDictionary(this);
- Register(this);
-
- // Only register the TinyMessenger singleton if we are the root container
- if (Parent == null)
- Register();
- }
-
- private DependencyContainer(DependencyContainer parent)
- : this()
- {
- Parent = parent;
- }
-
- ///
- /// Lazy created Singleton instance of the container for simple scenarios.
- ///
- public static DependencyContainer Current { get; } = new DependencyContainer();
-
- internal DependencyContainer Parent { get; }
-
- internal TypesConcurrentDictionary RegisteredTypes { get; }
-
- ///
- public void Dispose()
- {
- if (_disposed) return;
-
- _disposed = true;
-
- foreach (var disposable in RegisteredTypes.Values.Select(item => item as IDisposable))
- {
- disposable?.Dispose();
- }
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Gets the child container.
- ///
- /// A new instance of the class.
- public DependencyContainer GetChildContainer() => new DependencyContainer(this);
-
- #region Registration
-
-#if !NETSTANDARD1_3
- ///
- /// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
- /// Types will only be registered if they pass the supplied registration predicate.
- ///
- /// What action to take when encountering duplicate implementations of an interface/base class.
- /// Predicate to determine if a particular type should be registered.
- public void AutoRegister(
- DependencyContainerDuplicateImplementationActions duplicateAction =
- DependencyContainerDuplicateImplementationActions.RegisterSingle,
- Func registrationPredicate = null)
- {
- AutoRegister(
- Runtime.GetAssemblies().Where(a => !IsIgnoredAssembly(a)),
- duplicateAction,
- registrationPredicate);
- }
+ public DependencyContainer() {
+ this.RegisteredTypes = new TypesConcurrentDictionary(this);
+ _ = this.Register(this);
+
+ // Only register the TinyMessenger singleton if we are the root container
+ if(this.Parent == null) {
+ _ = this.Register();
+ }
+ }
+
+ private DependencyContainer(DependencyContainer parent)
+ : this() => this.Parent = parent;
+
+ ///
+ /// Lazy created Singleton instance of the container for simple scenarios.
+ ///
+ public static DependencyContainer Current { get; } = new DependencyContainer();
+
+ internal DependencyContainer Parent {
+ get;
+ }
+
+ internal TypesConcurrentDictionary RegisteredTypes {
+ get;
+ }
+
+ ///
+ public void Dispose() {
+ if(this._disposed) {
+ return;
+ }
+
+ this._disposed = true;
+
+ foreach(IDisposable disposable in this.RegisteredTypes.Values.Select(item => item as IDisposable)) {
+ disposable?.Dispose();
+ }
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Gets the child container.
+ ///
+ /// A new instance of the class.
+ public DependencyContainer GetChildContainer() => new DependencyContainer(this);
+
+ #region Registration
+
+#if !NETSTANDARD1_3
+ ///
+ /// Attempt to automatically register all non-generic classes and interfaces in the current app domain.
+ /// Types will only be registered if they pass the supplied registration predicate.
+ ///
+ /// What action to take when encountering duplicate implementations of an interface/base class.
+ /// Predicate to determine if a particular type should be registered.
+ public void AutoRegister(
+ DependencyContainerDuplicateImplementationActions duplicateAction =
+ DependencyContainerDuplicateImplementationActions.RegisterSingle,
+ Func registrationPredicate = null) => this.AutoRegister(
+ Runtime.GetAssemblies().Where(a => !IsIgnoredAssembly(a)),
+ duplicateAction,
+ registrationPredicate);
#endif
-
- ///
- /// Attempt to automatically register all non-generic classes and interfaces in the specified assemblies
- /// Types will only be registered if they pass the supplied registration predicate.
- ///
- /// Assemblies to process.
- /// What action to take when encountering duplicate implementations of an interface/base class.
- /// Predicate to determine if a particular type should be registered.
- public void AutoRegister(
- IEnumerable assemblies,
- DependencyContainerDuplicateImplementationActions duplicateAction =
- DependencyContainerDuplicateImplementationActions.RegisterSingle,
- Func registrationPredicate = null)
- {
- lock (_autoRegisterLock)
- {
- var types = assemblies
- .SelectMany(a => a.GetAllTypes())
- .Where(t => !IsIgnoredType(t, registrationPredicate))
- .ToList();
-
- var concreteTypes = types
- .Where(type =>
- type.IsClass() && !type.IsAbstract() &&
- (type != GetType() && (type.DeclaringType != GetType()) && !type.IsGenericTypeDefinition()))
- .ToList();
-
- foreach (var type in concreteTypes)
- {
- try
- {
- RegisteredTypes.Register(type, string.Empty, GetDefaultObjectFactory(type, type));
- }
- catch (MethodAccessException)
- {
- // Ignore methods we can't access - added for Silverlight
- }
- }
-
- var abstractInterfaceTypes = types.Where(
- type =>
- ((type.IsInterface() || type.IsAbstract()) && (type.DeclaringType != GetType()) &&
- (!type.IsGenericTypeDefinition())));
-
- foreach (var type in abstractInterfaceTypes)
- {
- var localType = type;
- var implementations = concreteTypes
- .Where(implementationType => localType.IsAssignableFrom(implementationType)).ToList();
-
- if (implementations.Skip(1).Any())
- {
- if (duplicateAction == DependencyContainerDuplicateImplementationActions.Fail)
- throw new DependencyContainerRegistrationException(type, implementations);
-
- if (duplicateAction == DependencyContainerDuplicateImplementationActions.RegisterMultiple)
- {
- RegisterMultiple(type, implementations);
- }
- }
-
- var firstImplementation = implementations.FirstOrDefault();
-
- if (firstImplementation == null) continue;
-
- try
- {
- RegisteredTypes.Register(type, string.Empty, GetDefaultObjectFactory(type, firstImplementation));
- }
- catch (MethodAccessException)
- {
- // Ignore methods we can't access - added for Silverlight
- }
- }
- }
- }
-
- ///
- /// Creates/replaces a named container class registration with default options.
- ///
- /// Type to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(Type registerType, string name = "")
- => RegisteredTypes.Register(
- registerType,
- name,
- GetDefaultObjectFactory(registerType, registerType));
-
- ///
- /// Creates/replaces a named container class registration with a given implementation and default options.
- ///
- /// Type to register.
- /// Type to instantiate that implements RegisterType.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(Type registerType, Type registerImplementation, string name = "") =>
- RegisteredTypes.Register(registerType, name, GetDefaultObjectFactory(registerType, registerImplementation));
-
- ///
- /// Creates/replaces a named container class registration with a specific, strong referenced, instance.
- ///
- /// Type to register.
- /// Instance of RegisterType to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(Type registerType, object instance, string name = "") =>
- RegisteredTypes.Register(registerType, name, new InstanceFactory(registerType, registerType, instance));
-
- ///
- /// Creates/replaces a named container class registration with a specific, strong referenced, instance.
- ///
- /// Type to register.
- /// Type of instance to register that implements RegisterType.
- /// Instance of RegisterImplementation to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(
- Type registerType,
- Type registerImplementation,
- object instance,
- string name = "")
- => RegisteredTypes.Register(registerType, name, new InstanceFactory(registerType, registerImplementation, instance));
-
- ///
- /// Creates/replaces a container class registration with a user specified factory.
- ///
- /// Type to register.
- /// Factory/lambda that returns an instance of RegisterType.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(
- Type registerType,
- Func, object> factory,
- string name = "")
- => RegisteredTypes.Register(registerType, name, new DelegateFactory(registerType, factory));
-
- ///
- /// Creates/replaces a named container class registration with default options.
- ///
- /// Type to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(string name = "")
- where TRegister : class
- {
- return Register(typeof(TRegister), name);
- }
-
- ///
- /// Creates/replaces a named container class registration with a given implementation and default options.
- ///
- /// Type to register.
- /// Type to instantiate that implements RegisterType.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(string name = "")
- where TRegister : class
- where TRegisterImplementation : class, TRegister
- {
- return Register(typeof(TRegister), typeof(TRegisterImplementation), name);
- }
-
- ///
- /// Creates/replaces a named container class registration with a specific, strong referenced, instance.
- ///
- /// Type to register.
- /// Instance of RegisterType to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(TRegister instance, string name = "")
- where TRegister : class
- {
- return Register(typeof(TRegister), instance, name);
- }
-
- ///
- /// Creates/replaces a named container class registration with a specific, strong referenced, instance.
- ///
- /// Type to register.
- /// Type of instance to register that implements RegisterType.
- /// Instance of RegisterImplementation to register.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(TRegisterImplementation instance,
- string name = "")
- where TRegister : class
- where TRegisterImplementation : class, TRegister
- {
- return Register(typeof(TRegister), typeof(TRegisterImplementation), instance, name);
- }
-
- ///
- /// Creates/replaces a named container class registration with a user specified factory.
- ///
- /// Type to register.
- /// Factory/lambda that returns an instance of RegisterType.
- /// Name of registration.
- /// RegisterOptions for fluent API.
- public RegisterOptions Register(
- Func, TRegister> factory, string name = "")
- where TRegister : class
- {
- if (factory == null)
- {
- throw new ArgumentNullException(nameof(factory));
- }
-
- return Register(typeof(TRegister), factory, name);
- }
-
- ///
- /// Register multiple implementations of a type.
- ///
- /// Internally this registers each implementation using the full name of the class as its registration name.
- ///
- /// Type that each implementation implements.
- /// Types that implement RegisterType.
- /// MultiRegisterOptions for the fluent API.
- public MultiRegisterOptions RegisterMultiple(IEnumerable implementationTypes) =>
- RegisterMultiple(typeof(TRegister), implementationTypes);
-
- ///
- /// Register multiple implementations of a type.
- ///
- /// Internally this registers each implementation using the full name of the class as its registration name.
- ///
- /// Type that each implementation implements.
- /// Types that implement RegisterType.
- /// MultiRegisterOptions for the fluent API.
- public MultiRegisterOptions RegisterMultiple(Type registrationType, IEnumerable implementationTypes)
- {
- if (implementationTypes == null)
- throw new ArgumentNullException(nameof(implementationTypes), "types is null.");
-
- foreach (var type in implementationTypes.Where(type => !registrationType.IsAssignableFrom(type)))
- {
- throw new ArgumentException(
- $"types: The type {registrationType.FullName} is not assignable from {type.FullName}");
- }
-
- if (implementationTypes.Count() != implementationTypes.Distinct().Count())
- {
- var queryForDuplicatedTypes = implementationTypes
- .GroupBy(i => i)
- .Where(j => j.Count() > 1)
- .Select(j => j.Key.FullName);
-
- var fullNamesOfDuplicatedTypes = string.Join(",\n", queryForDuplicatedTypes.ToArray());
-
- throw new ArgumentException(
- $"types: The same implementation type cannot be specified multiple times for {registrationType.FullName}\n\n{fullNamesOfDuplicatedTypes}");
- }
-
- var registerOptions = implementationTypes
- .Select(type => Register(registrationType, type, type.FullName))
- .ToList();
-
- return new MultiRegisterOptions(registerOptions);
- }
-
- #endregion
-
- #region Unregistration
-
- ///
- /// Remove a named container class registration.
- ///
- /// Type to unregister.
- /// Name of registration.
- /// true if the registration is successfully found and removed; otherwise, false.
- public bool Unregister(string name = "") => Unregister(typeof(TRegister), name);
-
- ///
- /// Remove a named container class registration.
- ///
- /// Type to unregister.
- /// Name of registration.
- /// true if the registration is successfully found and removed; otherwise, false.
- public bool Unregister(Type registerType, string name = "") =>
- RegisteredTypes.RemoveRegistration(new TypeRegistration(registerType, name));
-
- #endregion
-
- #region Resolution
-
- ///
- /// Attempts to resolve a named type using specified options and the supplied constructor parameters.
- ///
- /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
- /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolution options.
- /// Instance of type.
- /// Unable to resolve the type.
- public object Resolve(
- Type resolveType,
- string name = null,
- DependencyContainerResolveOptions options = null)
- => RegisteredTypes.ResolveInternal(new TypeRegistration(resolveType, name), options ?? DependencyContainerResolveOptions.Default);
-
- ///
- /// Attempts to resolve a named type using specified options and the supplied constructor parameters.
- ///
- /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
- /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolution options.
- /// Instance of type.
- /// Unable to resolve the type.
- public TResolveType Resolve(
- string name = null,
- DependencyContainerResolveOptions options = null)
- where TResolveType : class
- {
- return (TResolveType)Resolve(typeof(TResolveType), name, options);
- }
-
- ///
- /// Attempts to predict whether a given type can be resolved with the supplied constructor parameters options.
- /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
- /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
- /// Note: Resolution may still fail if user defined factory registrations fail to construct objects when called.
- ///
- /// Type to resolve.
- /// The name.
- /// Resolution options.
- ///
- /// Bool indicating whether the type can be resolved.
- ///
- public bool CanResolve(
- Type resolveType,
- string name = null,
- DependencyContainerResolveOptions options = null) =>
- RegisteredTypes.CanResolve(new TypeRegistration(resolveType, name), options);
-
- ///
- /// Attempts to predict whether a given named type can be resolved with the supplied constructor parameters options.
- ///
- /// Parameters are used in conjunction with normal container resolution to find the most suitable constructor (if one exists).
- /// All user supplied parameters must exist in at least one resolvable constructor of RegisterType or resolution will fail.
- ///
- /// Note: Resolution may still fail if user defined factory registrations fail to construct objects when called.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolution options.
- /// Bool indicating whether the type can be resolved.
- public bool CanResolve(
- string name = null,
- DependencyContainerResolveOptions options = null)
- where TResolveType : class
- {
- return CanResolve(typeof(TResolveType), name, options);
- }
-
- ///
- /// Attempts to resolve a type using the default options.
- ///
- /// Type to resolve.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(Type resolveType, out object resolvedType)
- {
- try
- {
- resolvedType = Resolve(resolveType);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = null;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the given options.
- ///
- /// Type to resolve.
- /// Resolution options.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(Type resolveType, DependencyContainerResolveOptions options, out object resolvedType)
- {
- try
- {
- resolvedType = Resolve(resolveType, options: options);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = null;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the default options and given name.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(Type resolveType, string name, out object resolvedType)
- {
- try
- {
- resolvedType = Resolve(resolveType, name);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = null;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the given options and name.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolution options.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(
- Type resolveType,
- string name,
- DependencyContainerResolveOptions options,
- out object resolvedType)
- {
- try
- {
- resolvedType = Resolve(resolveType, name, options);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = null;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the default options.
- ///
- /// Type to resolve.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(out TResolveType resolvedType)
- where TResolveType : class
- {
- try
- {
- resolvedType = Resolve();
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = default;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the given options.
- ///
- /// Type to resolve.
- /// Resolution options.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(DependencyContainerResolveOptions options, out TResolveType resolvedType)
- where TResolveType : class
- {
- try
- {
- resolvedType = Resolve(options: options);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = default;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the default options and given name.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(string name, out TResolveType resolvedType)
- where TResolveType : class
- {
- try
- {
- resolvedType = Resolve(name);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = default;
- return false;
- }
- }
-
- ///
- /// Attempts to resolve a type using the given options and name.
- ///
- /// Type to resolve.
- /// Name of registration.
- /// Resolution options.
- /// Resolved type or default if resolve fails.
- /// true if resolved successfully, false otherwise.
- public bool TryResolve(
- string name,
- DependencyContainerResolveOptions options,
- out TResolveType resolvedType)
- where TResolveType : class
- {
- try
- {
- resolvedType = Resolve(name, options);
- return true;
- }
- catch (DependencyContainerResolutionException)
- {
- resolvedType = default;
- return false;
- }
- }
-
- ///
- /// Returns all registrations of a type.
- ///
- /// Type to resolveAll.
- /// Whether to include un-named (default) registrations.
- /// IEnumerable.
- public IEnumerable