Skip to content

Commit

Permalink
Merge pull request #10 from DyegoMaas/feature/property-change-callbacks
Browse files Browse the repository at this point in the history
Added support for callbacks
  • Loading branch information
DyegoMaas authored Feb 25, 2022
2 parents bb4c521 + 10018e5 commit 1a61e41
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 33 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,15 @@ You can always override the behavior for a specific scenario:
instance.Name.Should().BeNull();
```

### Callbacks

```csharp
var project = MagicFactory.For<Project>()
.With(x => x.ProjectName = "Apollo")
.Do(x => Console.WriteLine(x.ProjectName) // prints "Apollo"
.Build();
```

## How to contribute

You can help this project in many ways. Here are some ideas:
Expand Down
7 changes: 7 additions & 0 deletions src/ForeverFactory/Customizations/CustomizeFactoryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,12 @@ public ICustomizeFactoryOptions<T> Set<TValue>(Func<T, TValue> setMember)
_objectFactoryOptions.Transforms.Add(new FuncTransform<T, TValue>(setMember.Invoke));
return this;
}

public ICustomizeFactoryOptions<T> Do(Action<T> callback)
{
var function = callback.WrapAsFunction();
_objectFactoryOptions.Transforms.Add(new FuncTransform<T, bool>(function.Invoke));
return this;
}
}
}
18 changes: 18 additions & 0 deletions src/ForeverFactory/Extensions/ActionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace ForeverFactory
{
internal static class ActionExtensions
{
public static Func<T, bool> WrapAsFunction<T>(this Action<T> callback)
{
bool Wrapper(T instance)
{
callback.Invoke(instance);
return true;
}

return Wrapper;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,13 @@ public interface ICustomizeManyBuildMany<out T> : IBuildMany<T>, INavigable<T>
/// <example>x => x.Name = "Karen"</example>
/// </param>
ICustomizeManyBuildMany<T> WithLast<TValue>(int count, Func<T, TValue> setMember);

/// <summary>
/// Executes the callback passing the instance with its current state.
/// </summary>
/// <param name="callback">
/// <example>x => Console.WriteLine(x.Name)</example>
/// </param>
ICustomizeManyBuildMany<T> Do(Action<T> callback);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,13 @@ public interface ICustomizeOneBuildManyWithNavigation<out T> : IBuildMany<T>, IN
/// <example>x => x.Name = "Karen"</example>
/// </param>
ICustomizeOneBuildManyWithNavigation<T> With<TValue>(Func<T, TValue> setMember);

/// <summary>
/// Executes the callback passing the instance with its current state.
/// </summary>
/// <param name="callback">
/// <example>x => Console.WriteLine(x.Name)</example>
/// </param>
ICustomizeOneBuildManyWithNavigation<T> Do(Action<T> callback);
}
}
8 changes: 8 additions & 0 deletions src/ForeverFactory/FluentInterfaces/ICustomizeOneBuildOne.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@ public interface ICustomizeOneBuildOne<out T> : IBuildOne<T>
/// >
/// </param>
ICustomizeOneBuildOne<T> With<TValue>(Func<T, TValue> setMember);

/// <summary>
/// Executes the callback passing the instance with its current state.
/// </summary>
/// <param name="callback">
/// <example>x => Console.WriteLine(x.Name)</example>
/// </param>
ICustomizeOneBuildOne<T> Do(Action<T> callback);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,13 @@ public interface ICustomizeOneBuildOneWithNavigation<out T> : IBuildOne<T>, INav
/// >
/// </param>
ICustomizeOneBuildOneWithNavigation<T> With<TValue>(Func<T, TValue> setMember);

/// <summary>
/// Executes the callback passing the instance with its current state.
/// </summary>
/// <param name="callback">
/// <example>x => Console.WriteLine(x.Name)</example>
/// </param>
ICustomizeOneBuildOneWithNavigation<T> Do(Action<T> callback);
}
}
1 change: 1 addition & 0 deletions src/ForeverFactory/ICustomizeFactoryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public interface ICustomizeFactoryOptions<T>
ICustomizeFactoryOptions<T> UseConstructor(Func<T> customConstructor);
ICustomizeFactoryOptions<T> SetDefaultBehavior(Behavior behavior);
ICustomizeFactoryOptions<T> Set<TValue>(Func<T, TValue> setMember);
ICustomizeFactoryOptions<T> Do(Action<T> callback);
}
}
93 changes: 60 additions & 33 deletions src/ForeverFactory/MagicFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ protected override void Customize(ICustomizeFactoryOptions<T> customization)
/// A customizable factory of objects of type "T". It can be extended with predefined configurations.
/// </summary>
/// <typeparam name="T">The type of objects that this factory will build.</typeparam>
public abstract class MagicFactory<T> : ISimpleFactory<T>, ICustomizeOneBuildOneWithNavigation<T>, ICustomizeManyBuildMany<T>, ICustomizeOneBuildManyWithNavigation<T>
public abstract class MagicFactory<T> : ISimpleFactory<T>, ICustomizeOneBuildOneWithNavigation<T>,
ICustomizeManyBuildMany<T>, ICustomizeOneBuildManyWithNavigation<T>
where T : class
{
private readonly ObjectBuilder<T> _objectBuilder;
Expand Down Expand Up @@ -71,34 +72,22 @@ public ISimpleFactory<T> WithBehavior(Behavior behavior)
return this;
}

public ICustomizeOneBuildOne<T> With<TValue>(Func<T, TValue> setMember)
{
AddTransformThatAlwaysApply(setMember);
return this;
}

ICustomizeOneBuildOneWithNavigation<T> ICustomizeOneBuildOneWithNavigation<T>.With<TValue>(Func<T, TValue> setMember)
public ICustomizeOneBuildOneWithNavigation<T> One()
{
AddTransformThatAlwaysApply(setMember);
return this;
}

public ICustomizeOneBuildOneWithNavigation<T> One()
public ICustomizeManyBuildMany<T> Many(int count)
{
SetRootNode(instanceCount: count);
return this;
}

public ICustomizeOneBuildManyWithNavigation<T> PlusOne()
{
var newNode = new GeneratorNode<T>(instanceCount: 1);
_objectBuilder.AddNode(newNode);

return this;
}

public ICustomizeManyBuildMany<T> Many(int count)
{
SetRootNode(instanceCount: count);
return this;
}

Expand All @@ -110,17 +99,21 @@ public ICustomizeManyBuildMany<T> Plus(int count)
return this;
}

public T Build()
public ICustomizeOneBuildOne<T> With<TValue>(Func<T, TValue> setMember)
{
return _objectBuilder.Build().First();
AddTransformThatAlwaysApply(setMember);
return this;
}

IEnumerable<T> IBuildMany<T>.Build()
ICustomizeOneBuildOneWithNavigation<T> ICustomizeOneBuildOneWithNavigation<T>.With<TValue>(
Func<T, TValue> setMember)
{
return _objectBuilder.Build();
AddTransformThatAlwaysApply(setMember);
return this;
}

ICustomizeOneBuildManyWithNavigation<T> ICustomizeOneBuildManyWithNavigation<T>.With<TValue>(Func<T, TValue> setMember)
ICustomizeOneBuildManyWithNavigation<T> ICustomizeOneBuildManyWithNavigation<T>.With<TValue>(
Func<T, TValue> setMember)
{
AddTransformThatAlwaysApply(setMember);
return this;
Expand All @@ -132,20 +125,52 @@ ICustomizeManyBuildMany<T> ICustomizeManyBuildMany<T>.With<TValue>(Func<T, TValu
return this;
}

private void AddTransformThatAlwaysApply<TValue>(Func<T, TValue> setMember)
public ICustomizeManyBuildMany<T> WithFirst<TValue>(int count, Func<T, TValue> setMember)
{
_objectBuilder.AddTransform(
new FuncTransform<T, TValue>(setMember.Invoke),
node => new AlwaysApplyTransformSpecification()
);
AddTransformThatAppliesToFirstNInstances(count, setMember);
return this;
}

public ICustomizeManyBuildMany<T> WithFirst<TValue>(int count, Func<T, TValue> setMember)
public ICustomizeManyBuildMany<T> WithLast<TValue>(int count, Func<T, TValue> setMember)
{
AddTransformThatAppliesToFirstNInstances(count, setMember);
AddTransformThatAppliesToLastNInstances(count, setMember);
return this;
}

ICustomizeOneBuildManyWithNavigation<T> ICustomizeOneBuildManyWithNavigation<T>.Do(Action<T> callback)
{
AddTransformThatAlwaysApply(callback.WrapAsFunction());
return this;
}

ICustomizeOneBuildOneWithNavigation<T> ICustomizeOneBuildOneWithNavigation<T>.Do(Action<T> callback)
{
AddTransformThatAlwaysApply(callback.WrapAsFunction());
return this;
}

ICustomizeOneBuildOne<T> ICustomizeOneBuildOne<T>.Do(Action<T> callback)
{
AddTransformThatAlwaysApply(callback.WrapAsFunction());
return this;
}

ICustomizeManyBuildMany<T> ICustomizeManyBuildMany<T>.Do(Action<T> callback)
{
AddTransformThatAlwaysApply(callback.WrapAsFunction());
return this;
}

public T Build()
{
return _objectBuilder.Build().First();
}

IEnumerable<T> IBuildMany<T>.Build()
{
return _objectBuilder.Build();
}

private void AddTransformThatAppliesToFirstNInstances<TValue>(int count, Func<T, TValue> setMember)
{
_objectBuilder.AddTransform(
Expand All @@ -154,17 +179,19 @@ private void AddTransformThatAppliesToFirstNInstances<TValue>(int count, Func<T,
);
}

public ICustomizeManyBuildMany<T> WithLast<TValue>(int count, Func<T, TValue> setMember)
private void AddTransformThatAppliesToLastNInstances<TValue>(int count, Func<T, TValue> setMember)
{
AddTransformThatAppliesToLastNInstances(count, setMember);
return this;
_objectBuilder.AddTransform(
new FuncTransform<T, TValue>(setMember.Invoke),
node => new ApplyTransformToLastInstancesSpecification(count, node.InstanceCount)
);
}

private void AddTransformThatAppliesToLastNInstances<TValue>(int count, Func<T, TValue> setMember)
private void AddTransformThatAlwaysApply<TValue>(Func<T, TValue> setMember)
{
_objectBuilder.AddTransform(
new FuncTransform<T, TValue>(setMember.Invoke),
node => new ApplyTransformToLastInstancesSpecification(count, node.InstanceCount)
node => new AlwaysApplyTransformSpecification()
);
}
}
Expand Down
Loading

0 comments on commit 1a61e41

Please sign in to comment.