Refactoring

- cleanup structure and CI pipeline
- Only publish if release with tag
This commit is contained in:
Peter 2020-03-10 21:53:04 +01:00
parent 5ec141c801
commit e291f691f1
Signed by: prskr
GPG key ID: 2285CF1BAF6ACCAA
12 changed files with 148 additions and 89 deletions

View file

@ -1,16 +1,11 @@
name: .NET Core
name: Publish
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
tags:
- '**'
jobs:
build:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
@ -20,9 +15,6 @@ jobs:
source-url: https://nuget.pkg.github.com/baez90/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Build with dotnet
run: dotnet build --configuration Release
working-directory: ./src/tand/
- name: Pack for deploying package
run: dotnet pack --configuration Release
working-directory: ./src/tand/

26
.github/workflows/validate.yml vendored Normal file
View file

@ -0,0 +1,26 @@
name: Validate
on:
push:
branches: [ '**' ]
pull_request:
branches: [ '**' ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1.4.0
with:
dotnet-version: 3.1.101
source-url: https://nuget.pkg.github.com/baez90/index.json
env:
NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Build with dotnet
run: dotnet build --configuration Release
working-directory: ./src/tand/
- name: Run tests
run: dotnet test --configuration Release --no-build
working-directory: ./src/tand/

View file

@ -5,31 +5,21 @@ namespace Tand.Core.Tests
{
public class LogTarget<T> : ITandTarget<T>
{
private readonly Action<string> _logHandle;
private readonly Action<T> _instanceHandle;
public LogTarget(Action<string> logHandle)
public LogTarget(Action<T> instanceHandle)
{
_logHandle = logHandle;
_instanceHandle = instanceHandle;
}
public void OnEnterMethod(CallEnterContext<T> enterContext)
{
_logHandle(enterContext.Instance.ToString());
foreach (var (name, val) in enterContext.Arguments)
{
_logHandle($"name: {name}, value: {val}");
}
_instanceHandle(enterContext.Instance);
}
public void OnLeaveMethod(CallLeaveContext<T> callLeaveContext)
{
_logHandle(callLeaveContext.Instance.ToString());
foreach (var (name, val) in callLeaveContext.Arguments)
{
_logHandle($"name: {name}, value: {val}");
}
_logHandle($"result: {callLeaveContext.CallResult}");
_instanceHandle(callLeaveContext.Instance);
}
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Tand.Core.Tests
{
internal class ResolverMock : IDependencyResolver
{
private readonly IDictionary<Type, object> _targets;
internal ResolverMock(params object[] targets)
{
_targets = targets.ToDictionary(target => target.GetType(), target => target);
}
public ITandTarget<T> TargetOfType<T>(Type type)
{
ResolvingCounter++;
return (ITandTarget<T>)_targets[type];
}
internal int ResolvingCounter { get; private set; }
}
}

View file

@ -2,8 +2,9 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View file

@ -1,55 +1,17 @@
using System;
using Xunit;
using Xunit.Abstractions;
namespace Tand.Core.Tests
{
public class TandTest
public interface ITandSample
{
private readonly ITestOutputHelper _outputHelper;
public TandTest(ITestOutputHelper outputHelper)
{
_outputHelper = outputHelper;
}
[Fact]
public void GenerateTand()
{
var tand = new Tand(new SampleResolver(_outputHelper));
var sample = tand.DecorateWithTand<ITAndSample, TandSample>(new TandSample());
var result = sample.LogMyParams("Hello, World", 42);
_outputHelper.WriteLine($"Got result: {result}");
}
}
public class SampleResolver : IDependencyResolver
{
private readonly ITestOutputHelper _outputHelper;
public SampleResolver(ITestOutputHelper outputHelper)
{
_outputHelper = outputHelper;
}
public ITandTarget<T> TargetOfType<T>(Type type)
{
return new LogTarget<T>(_outputHelper.WriteLine);
}
}
public interface ITAndSample
{
[Tand(typeof(LogTarget<TandSample>))]
[Tand(typeof(LogTarget<ITandSample>))]
int LogMyParams(string s, int i);
}
public class TandSample : ITAndSample
public class TandSample : ITandSample
{
private int _counter;
public string ContextSample { get; set; }
public int LogMyParams(string s, int i)

View file

@ -0,0 +1,22 @@
using Xunit;
namespace Tand.Core.Tests
{
public class TandTests
{
[Fact]
public void GenerateTand()
{
var handleCallCounter = 0;
var resolver = new ResolverMock(new LogTarget<ITandSample>(tandSample => handleCallCounter++));
var tand = new Tand(resolver);
var sample = tand.DecorateWithTand<ITandSample, TandSample>(new TandSample());
var result = sample.LogMyParams("Hello, World", 42);
Assert.Equal(1, result);
Assert.Equal(2, handleCallCounter);
Assert.Equal(1, resolver.ResolvingCounter);
}
}
}

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using Tand.Core.Models;
namespace Tand.Core
namespace Tand.Core.Models
{
public readonly struct CallEnterContext<T>
{

View file

@ -10,9 +10,15 @@ namespace Tand.Core
public class TandProxy<T> : DispatchProxy
{
private readonly IDictionary<int, Type[]> _targetCache;
private readonly Action<Exception>? _exceptionHandler;
public TandProxy()
public TandProxy() : this(null)
{
}
public TandProxy(Action<Exception>? exceptionHandler)
{
_exceptionHandler = exceptionHandler;
_targetCache = new ConcurrentDictionary<int, Type[]>();
}
@ -24,25 +30,56 @@ namespace Tand.Core
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var mappedMethodArgs = CollectArgs(targetMethod, args);
var enterContext = new CallEnterContext<T>(Decorated, mappedMethodArgs);
var targets = TargetTypesForMethod(targetMethod);
foreach (var target in targets)
{
target.OnEnterMethod(enterContext);
}
ProcessOnEntering(targets, new CallEnterContext<T>(Decorated, mappedMethodArgs));
var result = targetMethod.Invoke(Decorated, args);
var leaveContext = new CallLeaveContext<T>(Decorated, mappedMethodArgs, result);
foreach (var target in targets)
{
target.OnLeaveMethod(leaveContext);
}
ProcessOnLeaving(targets, new CallLeaveContext<T>(Decorated, mappedMethodArgs, result));
return result;
}
protected virtual void OnEnterMethod(ITandTarget<T> target, CallEnterContext<T> callEnterContext)
{
try
{
target.OnEnterMethod(callEnterContext);
}
catch (Exception e)
{
_exceptionHandler?.Invoke(e);
}
}
protected virtual void OnLeaveMethod(ITandTarget<T> target, CallLeaveContext<T> callLeaveContext)
{
try
{
target.OnLeaveMethod(callLeaveContext);
}
catch (Exception e)
{
_exceptionHandler?.Invoke(e);
}
}
private void ProcessOnEntering(IEnumerable<ITandTarget<T>> targets, CallEnterContext<T> callEnterContext)
{
foreach (var tandTarget in targets)
{
OnEnterMethod(tandTarget, callEnterContext);
}
}
private void ProcessOnLeaving(IEnumerable<ITandTarget<T>> targets, CallLeaveContext<T> callLeaveContext)
{
foreach (var tandTarget in targets)
{
OnLeaveMethod(tandTarget, callLeaveContext);
}
}
private static IDictionary<string, object> CollectArgs(MethodBase methodInfo, IReadOnlyList<object> argValues)
{
var result = new Dictionary<string, object>();

View file

@ -2,8 +2,9 @@
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View file

@ -1,5 +1,6 @@
using System;
using Tand.Core;
using Tand.Core.Models;
namespace Tand.Extensions.DependencyInjection
{

View file

@ -8,7 +8,7 @@ namespace Tand.Extensions.DependencyInjection
{
public static void AddTand(this IServiceCollection serviceCollection)
{
serviceCollection.TryAddSingleton(sp => new Tand.Core.Tand(new DependencyResolverProxy(sp)));
serviceCollection.TryAddSingleton(sp => new Core.Tand(new DependencyResolverProxy(sp)));
}
public static IServiceCollection AddTandTransient<TService, TImplementation>(this IServiceCollection services)
@ -22,7 +22,7 @@ namespace Tand.Extensions.DependencyInjection
private static TService GetTandForType<TService, TImplementation>(IServiceProvider serviceProvider) where TImplementation : class, TService where TService : class
{
var tand = serviceProvider.GetService<Tand.Core.Tand>();
var tand = serviceProvider.GetService<Core.Tand>();
var instance = serviceProvider.GetService<TImplementation>();
var proxy = tand.DecorateWithTand<TService, TImplementation>(instance);
return proxy;