forked from flq/MemBus
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Built all infrastructure to support arbitrary subscriber instances. N…
…ot yet accessible via IBus
- Loading branch information
Showing
18 changed files
with
471 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,28 @@ | |||
namespace MemBus.Tests.Help | |||
{ | |||
public interface IClassicIHandleStuffI<in T> | |||
{ | |||
void Gimme(T theThing); | |||
} | |||
|
|||
public interface IInvalidHandlerInterfaceBecauseNoParameter | |||
{ | |||
void Gimme(); | |||
} | |||
|
|||
public interface IInvalidHandlerInterfaceBecauseTwoMethodsOfrequestedPattern | |||
{ | |||
void Gimme(object thing); | |||
void Gamme(object thang); | |||
} | |||
|
|||
public interface IInvalidHandlerInterfaceBecauseTwoParams | |||
{ | |||
void Gimme(object thing, object thang); | |||
} | |||
|
|||
public interface IInvalidHandlerInterfaceBecauseReturnType | |||
{ | |||
int Gimme(object thing); | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,19 @@ | |||
using System; | |||
|
|||
namespace MemBus.Tests.Help | |||
{ | |||
public interface ItfNonGenericForHandles | |||
{ | |||
void Handle(MessageA msg); | |||
} | |||
|
|||
class AHandlerThroughSimpleInterface : ItfNonGenericForHandles | |||
{ | |||
public int MsgCount; | |||
|
|||
public void Handle(MessageA msg) | |||
{ | |||
MsgCount++; | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,37 @@ | |||
using System; | |||
|
|||
namespace MemBus.Tests.Help | |||
{ | |||
public class SomeCrazyHandler : IClassicIHandleStuffI<MessageC>, IClassicIHandleStuffI<MessageB> | |||
{ | |||
public int MessageCCount; | |||
public int MessageACount; | |||
public int MessageBCount; | |||
public int MsgSpecialACount; | |||
|
|||
public void Gimme(MessageC theThing) | |||
{ | |||
MessageCCount++; | |||
} | |||
|
|||
public void Gimme(MessageB theThing) | |||
{ | |||
MessageBCount++; | |||
} | |||
|
|||
public void Handle(MessageA msg) | |||
{ | |||
MessageACount++; | |||
} | |||
|
|||
public void Handle(MessageB msg) | |||
{ | |||
MessageBCount++; | |||
} | |||
|
|||
public void Schmandle(MessageASpecialization msg) | |||
{ | |||
MsgSpecialACount++; | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,12 @@ | |||
namespace MemBus.Tests.Help | |||
{ | |||
public class SomeHandler | |||
{ | |||
public int MsgACalls; | |||
|
|||
public void Handle(MessageA msg) | |||
{ | |||
MsgACalls++; | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,111 @@ | |||
using System; | |||
using System.Linq; | |||
using MemBus.Setup; | |||
using MemBus.Subscribing; | |||
using MemBus.Tests.Help; | |||
using Moq; | |||
using NUnit.Framework; | |||
using MemBus.Tests.Frame; | |||
using MemBus.Support; | |||
|
|||
namespace MemBus.Tests | |||
{ | |||
[TestFixture] | |||
public class Using_SubscriptionAdapter_Service | |||
{ | |||
[Test] | |||
public void Unconfigured_setup_will_throw_invalid_op() | |||
{ | |||
var setup = new FlexibleSubscribeAdapter(); | |||
Assert.Throws<InvalidOperationException>(() => ((ISetup<IConfigurableBus>)setup).Accept(null)); | |||
} | |||
|
|||
[Test] | |||
public void When_having_some_configuration_adapter_adds_itself_as_service() | |||
{ | |||
var setup = new FlexibleSubscribeAdapter(); | |||
setup.ByMethodName("Handle"); | |||
|
|||
var bus = new Mock<IConfigurableBus>(); | |||
((ISetup<IConfigurableBus>)setup).Accept(bus.Object); | |||
|
|||
bus.Verify(c=>c.AddService<IAdapterServices>(setup)); | |||
} | |||
|
|||
[Test] | |||
public void Integrative_test_of_finding_all_handlers_in_complex_scenario() | |||
{ | |||
var setup = new FlexibleSubscribeAdapter(); | |||
setup | |||
.ByInterface(typeof(IClassicIHandleStuffI<>)) | |||
.ByMethodName("Handle") | |||
.ByMethodName("Schmandle"); | |||
|
|||
var handler = new SomeCrazyHandler(); | |||
var subs = ((IAdapterServices) setup).SubscriptionsFor(handler); | |||
|
|||
subs.ShouldHaveCount(5); | |||
|
|||
subs.Where(s=>s.Handles(typeof(MessageASpecialization))).Each(s=>s.Push(new MessageASpecialization())); | |||
handler.MessageACount.ShouldBeEqualTo(1); | |||
handler.MsgSpecialACount.ShouldBeEqualTo(1); | |||
|
|||
subs.Where(s => s.Handles(typeof(MessageB))).Each(s => s.Push(new MessageB())); | |||
handler.MessageBCount.ShouldBeEqualTo(2); //There are 2 handle methods for MsgB :) | |||
|
|||
subs.Where(s => s.Handles(typeof(MessageC))).Each(s => s.Push(new MessageC())); | |||
handler.MessageCCount.ShouldBeEqualTo(1); | |||
} | |||
|
|||
[Test] | |||
public void Subscriptions_are_built_for_object_method_based() | |||
{ | |||
var builder = new MethodBasedBuilder("Handle"); | |||
var subs = builder.BuildSubscriptions(new SomeHandler()); | |||
subs.ShouldNotBeNull(); | |||
subs.ShouldHaveCount(1); | |||
} | |||
|
|||
[Test] | |||
public void Subscriptions_for_object_method_based_work_correctly() | |||
{ | |||
var builder = new MethodBasedBuilder("Handle"); | |||
var handler = new SomeHandler(); | |||
var subs = builder.BuildSubscriptions(handler); | |||
var subscription = subs.First(); | |||
subscription.Handles(typeof(MessageA)).ShouldBeTrue(); | |||
subscription.Push(new MessageA()); | |||
handler.MsgACalls.ShouldBeEqualTo(1); | |||
} | |||
|
|||
[TestCase(typeof(IInvalidHandlerInterfaceBecauseNoParameter))] | |||
[TestCase(typeof(IInvalidHandlerInterfaceBecauseTwoMethodsOfrequestedPattern))] | |||
[TestCase(typeof(IInvalidHandlerInterfaceBecauseReturnType))] | |||
[TestCase(typeof(IInvalidHandlerInterfaceBecauseTwoParams))] | |||
public void These_handler_interfaces_are_invalid_for_usage(Type interfaceType) | |||
{ | |||
Assert.Throws<InvalidOperationException>(() => { new InterfaceBasedBuilder(interfaceType); }); | |||
} | |||
|
|||
[Test] | |||
public void Non_generic_interface_is_properly_handled() | |||
{ | |||
var builder = new InterfaceBasedBuilder(typeof(ItfNonGenericForHandles)); | |||
var targetToAdapt = new AHandlerThroughSimpleInterface(); | |||
var subs = builder.BuildSubscriptions(targetToAdapt); | |||
subs.ShouldHaveCount(1); | |||
var s = subs.First(); | |||
s.Handles(typeof(MessageA)).ShouldBeTrue(); | |||
s.Push(new MessageA()); | |||
targetToAdapt.MsgCount.ShouldBeEqualTo(1); | |||
} | |||
|
|||
[Test] | |||
public void Two_subscriptions_expected_from_aquainting_crazy_handler() | |||
{ | |||
var builder = new InterfaceBasedBuilder(typeof (IClassicIHandleStuffI<>)); | |||
var subs = builder.BuildSubscriptions(new SomeCrazyHandler()); | |||
subs.ShouldHaveCount(2); | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
MemBus/Subscribing/Adapter/ConstructSubscriptionExtension.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,28 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using System.Linq; | |||
|
|||
namespace MemBus.Subscribing | |||
{ | |||
public static class ConstructSubscriptionExtension | |||
{ | |||
public static ISubscription ConstructSubscription(this MethodInfo info, object target) | |||
{ | |||
var parameterType = info.GetParameters()[0].ParameterType; | |||
|
|||
var fittingDelegateType = typeof(Action<>).MakeGenericType(parameterType); | |||
var @delegate = Delegate.CreateDelegate(fittingDelegateType, target, info); | |||
|
|||
var fittingMethodSubscription = typeof(MethodInvocation<>).MakeGenericType(parameterType); | |||
var sub = Activator.CreateInstance(fittingMethodSubscription, @delegate); | |||
|
|||
return (ISubscription)sub; | |||
} | |||
|
|||
public static IEnumerable<ISubscription> ConstructSubscriptions(this IEnumerable<MethodInfo> infos, object target) | |||
{ | |||
return infos.Select(i => i.ConstructSubscription(target)); | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,53 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using MemBus.Setup; | |||
using System.Linq; | |||
|
|||
namespace MemBus.Subscribing | |||
{ | |||
public class FlexibleSubscribeAdapter : ISetup<IConfigurableBus>, IAdapterServices | |||
{ | |||
private bool configurationAvailable; | |||
private readonly List<ISubscriptionBuilder> builders = new List<ISubscriptionBuilder>(); | |||
|
|||
|
|||
void ISetup<IConfigurableBus>.Accept(IConfigurableBus setup) | |||
{ | |||
if (!configurationAvailable) | |||
throw new InvalidOperationException("No adapter rules were set up."); | |||
setup.AddService<IAdapterServices>(this); | |||
} | |||
|
|||
/// <summary> | |||
/// Look at an object and look for methods with the provided name. The method must be void | |||
/// and accept a single parameter | |||
/// </summary> | |||
public FlexibleSubscribeAdapter ByMethodName(string methodName) | |||
{ | |||
addToBuilders(new MethodBasedBuilder(methodName)); | |||
return this; | |||
} | |||
|
|||
/// <summary> | |||
/// Look at an object and check it for interfaces. An interface should adhere to the following rules: | |||
/// Interface should define only one void method with a single parameter. | |||
/// The interface may be generic and can be implemented multiple times. | |||
/// </summary> | |||
public FlexibleSubscribeAdapter ByInterface(Type interfaceType) | |||
{ | |||
addToBuilders(new InterfaceBasedBuilder(interfaceType)); | |||
return this; | |||
} | |||
|
|||
IEnumerable<ISubscription> IAdapterServices.SubscriptionsFor(object subscriber) | |||
{ | |||
return builders.SelectMany(b => b.BuildSubscriptions(subscriber)); | |||
} | |||
|
|||
private void addToBuilders(ISubscriptionBuilder builder) | |||
{ | |||
builders.Add(builder); | |||
configurationAvailable = true; | |||
} | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,9 @@ | |||
using System.Collections.Generic; | |||
|
|||
namespace MemBus.Subscribing | |||
{ | |||
public interface IAdapterServices | |||
{ | |||
IEnumerable<ISubscription> SubscriptionsFor(object subscriber); | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,9 @@ | |||
using System.Collections.Generic; | |||
|
|||
namespace MemBus.Subscribing | |||
{ | |||
public interface ISubscriptionBuilder | |||
{ | |||
IEnumerable<ISubscription> BuildSubscriptions(object targetToAdapt); | |||
} | |||
} |
Oops, something went wrong.