Skip to content

Commit

Permalink
Added abstraction for WaitHandle.
Browse files Browse the repository at this point in the history
Added convenience methods for conversion of arrays with abstractions to array with implementations and vice versa.
Added InstanceEqualityComparer.
Added AbstractionEventHandlerLookup for mapping eventhandler using abstractions to eventhandler using implementations.
  • Loading branch information
PawelGerr committed Nov 28, 2016
1 parent a7fa538 commit ddfa400
Show file tree
Hide file tree
Showing 18 changed files with 781 additions and 165 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
**/.vs/**
**/bin/**
**/obj/**
**/packages/**
*.xproj.user
project.lock.json

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ Provides interfaces for types in `System.Runtime.Handles`: `SafeHandle`, `Critic
**Nuget**: `Install-Package Thinktecture.Runtime.Handles.Abstractions`

### Thinktecture.Runtime.Abstractions
Provides interfaces for types in `System.Runtime`: `StringBuilder`, `EventArgs`.
Provides interfaces for types in `System.Runtime`: `StringBuilder`, `WaitHandle`, `EventArgs`.

**Nuget**: `Install-Package Thinktecture.Runtime.Abstractions`
33 changes: 33 additions & 0 deletions src/Thinktecture.Abstractions/AbstractionEventHandlerContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;

namespace Thinktecture
{
/// <summary>
/// Event handler context of an abstraction.
/// </summary>
/// <typeparam name="T"></typeparam>
public class AbstractionEventHandlerContext<T>
{
/// <summary>
/// Event handler.
/// </summary>
public EventHandler<T> Handler { get; }

/// <summary>
/// Indication how many times the handler has been attached.
/// </summary>
public int Count { get; set; }

/// <summary>
/// Initializes new istance of <see cref="AbstractionEventHandlerContext{T}"/>.
/// </summary>
/// <param name="handler">Event handler</param>
public AbstractionEventHandlerContext(EventHandler<T> handler)
{
if (handler == null)
throw new ArgumentNullException(nameof(handler));

Handler = handler;
}
}
}
72 changes: 72 additions & 0 deletions src/Thinktecture.Abstractions/AbstractionEventHandlerLookup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using Thinktecture.Collections.Generic;

namespace Thinktecture
{
/// <summary>
/// Allow mapping of event handlers.
/// </summary>
public class AbstractionEventHandlerLookup<TAbstraction, TImplementation>
where TAbstraction : IAbstraction
{
private readonly Dictionary<EventHandler<TAbstraction>, AbstractionEventHandlerContext<TImplementation>> _lookup;

/// <summary>
/// Initializes new instance of <see cref="AbstractionEventHandlerLookup{TAbstraction,TImplementation}"/>.
/// </summary>
public AbstractionEventHandlerLookup()
{
var comparer = new InstanceEqualityComparer<EventHandler<TAbstraction>>();
_lookup = new Dictionary<EventHandler<TAbstraction>, AbstractionEventHandlerContext<TImplementation>>(comparer);
}

/// <summary>
/// Maps handler for attaching to an event.
/// </summary>
/// <param name="handler">Handler to map.</param>
/// <param name="toInterface">Function to convert an implementation to an abstraction.</param>
/// <returns>Mapped handler</returns>
public EventHandler<TImplementation> MapForAttachment(EventHandler<TAbstraction> handler, Func<TImplementation, TAbstraction> toInterface)
{
if (handler == null)
return null;

if (toInterface == null)
throw new ArgumentNullException(nameof(toInterface));

AbstractionEventHandlerContext<TImplementation> ctx;
if (!_lookup.TryGetValue(handler, out ctx))
{
ctx = new AbstractionEventHandlerContext<TImplementation>((sender, args) => handler(sender, toInterface(args)));
_lookup.Add(handler, ctx);
}

ctx.Count++;

return ctx.Handler;
}

/// <summary>
/// Maps handler for detachment.
/// </summary>
/// <param name="handler">Handler to map.</param>
/// <returns>Mapped handler</returns>
public EventHandler<TImplementation> TryMapForDetachment(EventHandler<TAbstraction> handler)
{
AbstractionEventHandlerContext<TImplementation> ctx;

if (handler != null && _lookup.TryGetValue(handler, out ctx))
{
ctx.Count--;

if (ctx.Count <= 0)
_lookup.Remove(handler);

return ctx.Handler;
}

return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;

namespace Thinktecture.Collections.Generic
{
/// <summary>
/// Use <see cref="Object.ReferenceEquals"/> for comparison.
/// </summary>
/// <typeparam name="T">Type of item to compare.</typeparam>
public class InstanceEqualityComparer<T> : IEqualityComparer<T>
{
/// <inheritdoc />
public bool Equals(T x, T y)
{
return ReferenceEquals(x, y);
}

/// <inheritdoc />
public int GetHashCode(T obj)
{
return obj?.GetHashCode() ?? 0;
}
}
}
31 changes: 31 additions & 0 deletions src/Thinktecture.Abstractions/Extensions/ArrayExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Thinktecture.Extensions
{
/// <summary>
/// Extensions for arrays
/// </summary>
public static class ArrayExtensions
{
/// <summary>
/// Copies and converts abstractions to implementations.
/// </summary>
/// <typeparam name="TAbstraction">Type of the abstraction.</typeparam>
/// <typeparam name="TImplementation">Type of the implementation.</typeparam>
/// <param name="abstractions">Array with abstractions.</param>
/// <returns></returns>
public static TImplementation[] ToImplementation<TAbstraction, TImplementation>(this TAbstraction[] abstractions)
where TAbstraction : IAbstraction
{
if (abstractions == null)
return null;

var implementations = new TImplementation[abstractions.Length];

for (var i = 0; i < abstractions.Length; i++)
{
implementations[i] = (TImplementation) abstractions[i]?.UnsafeConvert();
}

return implementations;
}
}
}
7 changes: 3 additions & 4 deletions src/Thinktecture.Abstractions/project.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
{
"version": "1.0.0-*",
"title": "Thinktecture.Abstractions",
"copyright": "(c) 2016, Pawel Gerr. All rights reserved.",
Expand All @@ -14,15 +14,14 @@
"url": "git@github.com:PawelGerr/Thinktecture.Abstractions.git"
}
},

"buildOptions": {
"xmlDoc": true
},

"frameworks": {
"netstandard1.0": {
"dependencies": {
"System.Runtime": "4.3.0"
"System.Runtime": "4.3.0",
"System.Collections": "4.3.0"
}
},
"net45": {},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.IO;
using Thinktecture.IO;

namespace Thinktecture
{
/// <summary>
/// Extensions for arrays.
/// </summary>
public static class ArrayExtensions
{
/// <summary>
/// Converts an array of <see cref="DirectoryInfo"/> to an array of <see cref="IDirectoryInfo"/>.
/// </summary>
/// <param name="infos">Array to convert.</param>
/// <returns>An array of <see cref="IDirectoryInfo"/>.</returns>
public static IDirectoryInfo[] ToInterface(this DirectoryInfo[] infos)
{
if (infos == null)
return null;

var abstractions = new IDirectoryInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
abstractions[i] = infos[i].ToInterface();
}

return abstractions;
}

/// <summary>
/// Converts an array of <see cref="FileInfo"/> to an array of <see cref="IFileInfo"/>.
/// </summary>
/// <param name="infos">Array to convert.</param>
/// <returns>An array of <see cref="IFileInfo"/>.</returns>
public static IFileInfo[] ToInterface(this FileInfo[] infos)
{
if (infos == null)
return null;

var abstractions = new IFileInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
abstractions[i] = infos[i].ToInterface();
}

return abstractions;
}

/// <summary>
/// Converts an array of <see cref="FileSystemInfo"/> to an array of <see cref="IFileSystemInfo"/>.
/// </summary>
/// <param name="infos">Array to convert.</param>
/// <returns>An array of <see cref="IFileSystemInfo"/>.</returns>
public static IFileSystemInfo[] ToInterface(this FileSystemInfo[] infos)
{
if (infos == null)
return null;

var abstractions = new IFileSystemInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
abstractions[i] = infos[i].ToInterface();
}

return abstractions;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,55 +126,55 @@ public IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(string searchPatter
/// <inheritdoc />
public IDirectoryInfo[] GetDirectories()
{
return Convert(_instance.GetDirectories());
return _instance.GetDirectories().ToInterface();
}

/// <inheritdoc />
public IDirectoryInfo[] GetDirectories(string searchPattern)
{
return Convert(_instance.GetDirectories(searchPattern));
return _instance.GetDirectories(searchPattern).ToInterface();
}

/// <inheritdoc />
public IDirectoryInfo[] GetDirectories(string searchPattern, SearchOption searchOption)
{
return Convert(_instance.GetDirectories(searchPattern, searchOption));
return _instance.GetDirectories(searchPattern, searchOption).ToInterface();
}

/// <inheritdoc />
public IFileInfo[] GetFiles()
{
return Convert(_instance.GetFiles());
return _instance.GetFiles().ToInterface();
}

/// <inheritdoc />
public IFileInfo[] GetFiles(string searchPattern)
{
return Convert(_instance.GetFiles(searchPattern));
return _instance.GetFiles(searchPattern).ToInterface();
}

/// <inheritdoc />
public IFileInfo[] GetFiles(string searchPattern, SearchOption searchOption)
{
return Convert(_instance.GetFiles(searchPattern, searchOption));
return _instance.GetFiles(searchPattern, searchOption).ToInterface();
}

/// <inheritdoc />
public IFileSystemInfo[] GetFileSystemInfos()
{
return Convert(_instance.GetFileSystemInfos());
return _instance.GetFileSystemInfos().ToInterface();
}

/// <inheritdoc />
public IFileSystemInfo[] GetFileSystemInfos(string searchPattern)
{
return Convert(_instance.GetFileSystemInfos(searchPattern));
return _instance.GetFileSystemInfos(searchPattern).ToInterface();
}

/// <inheritdoc />
public IFileSystemInfo[] GetFileSystemInfos(string searchPattern, SearchOption searchOption)
{
return Convert(_instance.GetFileSystemInfos(searchPattern, searchOption));
return _instance.GetFileSystemInfos(searchPattern, searchOption).ToInterface();
}

/// <inheritdoc />
Expand Down Expand Up @@ -206,41 +206,5 @@ private IEnumerable<IFileSystemInfo> Convert(IEnumerable<FileSystemInfo> infos)
yield return info.ToInterface();
}
}

private IDirectoryInfo[] Convert(DirectoryInfo[] infos)
{
var interfaces = new IDirectoryInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
interfaces[i] = infos[i].ToInterface();
}

return interfaces;
}

private IFileInfo[] Convert(FileInfo[] infos)
{
var interfaces = new IFileInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
interfaces[i] = infos[i].ToInterface();
}

return interfaces;
}

private IFileSystemInfo[] Convert(FileSystemInfo[] infos)
{
var interfaces = new IFileSystemInfo[infos.Length];

for (var i = 0; i < infos.Length; i++)
{
interfaces[i] = infos[i].ToInterface();
}

return interfaces;
}
}
}
Loading

0 comments on commit ddfa400

Please sign in to comment.