Override custom registration conventions in StructureMap 3 - c#

I'm using CQRS pattern in my recent project and used Structuremap 3 as my IoC Container, So I defined following conversion to resolve ICommandHandlers for each BaseEntity types:
public class InsertCommandRegistrationConvention
: StructureMap.Graph.IRegistrationConvention
{
private static readonly Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type) &&
type.GetInterfaces().Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType =
_openInsertCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType =
_openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
registry.For(insertclosedHandlerInterfaceType)
.Use(closedInsertCommandHandlerType);
}
}
}
and used it in my CompositionRoot:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.TheCallingAssembly();
s.WithDefaultConventions();
s.Convention<InsertCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
}
so for each my entity it register appropriate InsertCommandHandler for example it register
the InsertCommandHandler<InsertCommandParameter<Order>> for ICommandHandler<ICommandParameter<Order>>
sometimes I need to register custom InsertCommandHandlers for some Entities for example for Product I want to register non-generic InsertProductCustomCommandHandler class for ICommandHandler<ICommandParameter<Product>> instead InsertCommandHandler<InsertCommandParameter<Product>>(in the other word, I want to override the InsertCommendRegistrationConvention).
How could I do this, with Structuremap 3?

You can do this with the method IContainer.Configure() - the Configure() method allows you to add additional configuration to an existing Container or ObjectFactory
I've simplified your abstractions to demonstrate this in action:
public abstract class BaseEntity { }
public interface ICommandHandler<T> { }
public class ClassA : BaseEntity { }
public class ClassB : BaseEntity { }
public class ClassC : BaseEntity { }
public class ClassD : BaseEntity { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialInsertDCommandHandler : ICommandHandler<ClassD> { }
And InsertCommandRegistrationConvention
public class InsertCommandRegistrationConvention : IRegistrationConvention
{
private static readonly Type _openHandlerInterfaceType =
typeof(ICommandHandler<>);
private static readonly Type _openInsertCommandHandlerType =
typeof(InsertCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type))
{
Type closedInsertCommandHandlerType =
_openInsertCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType =
_openHandlerInterfaceType.MakeGenericType(type);
registry.For(insertclosedHandlerInterfaceType)
.Use(closedInsertCommandHandlerType);
}
}
}
This test demonstrates that a container configured with InsertCommandRegistrationConvention will return the generic InsertCommandHandler<> for all 4 of the test classes ClassA to ClassD
[Test]
public void Handle_Initialize_RegistersClassesAToDToReturnInsertCommandHandler()
{
var container = ApplicationConfiguration.Initialize();
var resultA = container.GetInstance<ICommandHandler<ClassA>>();
var resultB = container.GetInstance<ICommandHandler<ClassB>>();
var resultC = container.GetInstance<ICommandHandler<ClassC>>();
var resultD = container.GetInstance<ICommandHandler<ClassD>>();
Assert.That(resultA.GetType() == typeof(InsertCommandHandler<ClassA>));
Assert.That(resultB.GetType() == typeof(InsertCommandHandler<ClassB>));
Assert.That(resultC.GetType() == typeof(InsertCommandHandler<ClassC>));
Assert.That(resultD.GetType() == typeof(InsertCommandHandler<ClassD>));
}
And this test shows the Configure method successfully updates the registration for ClassD to return SpecialInsertDCommandHandler instead of InsertCommandHandler<ClassD>
[Test]
public void Handle_Condfigure_OverridesRegistrationForClassD()
{
var container = ApplicationConfiguration.Initialize();
container.Configure(x =>
{
x.For<ICommandHandler<ClassD>>().Use<SpecialInsertDCommandHandler>();
});
var resultD = container.GetInstance<ICommandHandler<ClassD>>();
Assert.That(resultD.GetType() == typeof(SpecialInsertDCommandHandler));
}

You can modify the convention to say something like "If there's a specific command handler, use that. Otherwise, use the InsertCommandHandler."
It would look like this (like qujck, I simplified the classes):
public class InsertCommandRegistrationConvention : IRegistrationConvention
{
private static readonly Type _openHandlerInterfaceType = typeof (ICommandHandler<>);
private static readonly Type _openInsertCommandHandlerType = typeof (InsertCommandHandler<>);
private static readonly IList<Type> _customCommandHandlerTypes;
static InsertCommandRegistrationConvention()
{
_customCommandHandlerTypes = _openInsertCommandHandlerType
.Assembly
.ExportedTypes
.Where(x => !x.IsAbstract)
.Where(x => !x.IsGenericType || x.GetGenericTypeDefinition() != typeof (InsertCommandHandler<>))
.Where(x => x.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>)))
.ToArray();
}
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof (BaseEntity).IsAssignableFrom(type))
{
var insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(type);
var closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
// check for any classes that implement ICommandHandler<T> that are not also InsertCommandHandler<T>
var customHandler = _customCommandHandlerTypes.FirstOrDefault(t => t.GetInterfaces().Any(i => i == insertclosedHandlerInterfaceType));
registry.For(insertclosedHandlerInterfaceType)
.Use(customHandler ?? closedInsertCommandHandlerType);
}
}
}
The classes I used:
public abstract class BaseEntity { }
public class Class1 : BaseEntity { }
public class Class2 : BaseEntity { }
public class SpecialClass :BaseEntity { }
public interface ICommandHandler<T> { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialClassInsertCommandHandler : ICommandHandler<SpecialClass> { }
The tests that pass:
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class1>>(), Is.InstanceOf<InsertCommandHandler<Class1>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class2>>(), Is.InstanceOf<InsertCommandHandler<Class2>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<SpecialClass>>(), Is.InstanceOf<SpecialClassInsertCommandHandler>());
The advantage is that you modified your convention, rather than avoided using it for certain items. Which keeps everything in one spot if something about your logic has to change.

Related

chain of responsibility and generics

I have a chain of responsibility that applies filters to a collection. I am trying to make a factory to build that chain of responsibility from a configuration. My concrete types for the chain arent generic but their abstraction are, and the genericity makes me struggle to put them in a collection for a mapping between config and correct chain node implementation.
Here is the implementation of the chain :
public interface IFilter<T> where T : IFilterable
{
IFilter<T> SetNext(IFilter<T> next);
IEnumerable<T> Filter(IEnumerable<T> data);
}
public class BaseFilter<T> : IFilter<T> where T : IFilterable
{
protected IFilter<T> Next { get; set; }
public IFilter<T> SetNext(IFilter<T> next)
{
Next = next;
return Next;
}
public virtual IEnumerable<T> Filter(IEnumerable<T> data)
{
return Next == null ? data : Next.Filter(data);
}
}
Here is an example of concrete implementation of the nodes of the chain :
public interface IFilterable {}
public interface ICanFly: IFilterable
{
bool CanFly { get; }
}
public interface ITransport : IFilterable
{
int Passengers { get; }
}
public class Duck : ICanFly
{
public bool CanFly => true;
}
public class Plane : ICanFly, ITransport
{
public bool CanFly => true;
public int Passengers => 5;
}
public class FlyerFilter : BaseFilter<ICanFly>
{
public override IEnumerable<ICanFly> Filter(IEnumerable<ICanFly> data)
{
return base.Filter(data.Where(x => x.CanFly));
}
}
public class SmallTransportFilter : BaseFilter<ITransport>
{
public override IEnumerable<ITransport> Filter(IEnumerable<ITransport> data)
{
return base.Filter(data.Where(x => x.Passengers < 8));
}
}
My problems start when I want to make a factory that map the configuration to my concrete types (FlyerFilter and SmallTransportFilter in my example)
public interface IFilterChainBuilder<T> where T : IFilterable
{
IFilter<T> GenerateFilterResponsabilityChain(IEnumerable<string> filtersParam);
}
public class FilterChainBuilder<T> : IFilterChainBuilder<T> where T : IFilterable
{
private readonly Dictionary<string, IFilter<T>> _paramToFiltersMap;
public FilterChainBuilder()
{
_paramToFiltersMap = new Dictionary<string, IFilter<T>>(StringComparer.OrdinalIgnoreCase)
{
{"Flyers", new FlyerFilter()}, // Compile error, cannot convert from FlyerFilter to IFilter<T>
{"SmallTransport", new SmallTransportFilter()} // Compile error, cannot convert from SmallTransportFilter to IFilter<T>
};
}
public IFilter<T> GenerateFilterResponsabilityChain(IEnumerable<string> filtersParam)
{
IFilter<T> filterResponsabilityChain = null;
foreach (var parameter in filtersParam)
if (_paramToFiltersMap.TryGetValue(parameter, out var filter))
{
if (filterResponsabilityChain == null)
filterResponsabilityChain = filter;
else
filterResponsabilityChain.SetNext(filter);
}
else
{
throw new ArgumentException(
$"config parameter {parameter} has no associated IFilter");
}
return filterResponsabilityChain ?? new BaseFilter<T>();
}
}
I can understand why it doesnt compile. Since FlyerFilter is a BaseFilter<ICanFly> (so a IFilter<ICanFly>), it would be bad if I declared a new FilterChainBuilder<PlaceholderType>. And actually since SmallTransportFilter inherit from a different T type, the only possible IFilterable implementation would have to implement both ITransport and ICanFly.
I tried to remove the generic T type entirely but the consummer of this chain of responsability relies on that IEnumerable<T> Filter(IEnumerable<T> data) signature and wants an enumeration of concrete types rather than IFilterable.
I am not sure how could I fix this problem, I am currently stuck here.
Pavel is correct - Your definition of IFilter makes the type parameter T invariant. Putting covariance/controvariance/invariance aside, the design itself is questionable. For example, FlyFilter works only against ICanFly instances, but there is no code filters the input down to ICanFly elements only - shouldn't that be the responsibility of FlyFilter as well? I would personally suggest you use type info in your filters directly, maybe something like below:
public interface IFilterable { }
public class CanFly : IFilterable { }
public class Duck : CanFly { }
public abstract class Transportation : CanFly
{
public abstract int Passengers { get; }
}
public class Plane : Transportation
{
public override int Passengers => 5;
}
public class FlyerFilter : BaseFilter<IFilterable>
{
public override IEnumerable<IFilterable> Filter(IEnumerable<IFilterable> data)
{
return base.Filter(data.Where(x => x is CanFly));
}
}
public class SmallTransportFilter : BaseFilter<IFilterable>
{
public override IEnumerable<IFilterable> Filter(IEnumerable<IFilterable> data)
{
return base.Filter(data.Where(x => x is Transportation t && t.Passengers < 8));
}
}

Resolving IEnumerable of generic interfaces from Autofac container

I'm not sure if this is possible, I've seen some other posts asking similar question but none have a satisfactory answer.
What I want to do is resolve a collection of interfaces with differing generic types from Autofac. So constructor of class would look something like this:
public class SomeClass<T> where T : class
{
private readonly IEnumerable<ITestInterface<T>> _testInterfaces;
public SomeClass(IEnumerable<ITestInterface<T>> testInterfaces)
{
_testInterfaces = testInterfaces;
}
}
Ideally, I'd just like to be able to register each instance individually like so:
builder
.RegisterType<ImplementationA>()
.As<ITestInterface<A>>();
builder
.RegisterType<ImplementationB>()
.As<ITestInterface<B>>();
I've tried various combinations of RegisterGeneric etc but the Enumerable just keeps coming through empty.
Any help would be appreciated.
I was able to resolve this after playing with inheritance & generic constraints. The solution I ended up with looks like this:
Base classes / interfaces:
public abstract class BaseClass
{
public abstract string IAM { get; }
}
public interface ITestInterface<out T> where T : BaseClass
{
T GetSomething();
}
Implemented classes:
public class A : BaseClass
{
public override string IAM => "I AM TYPE A";
}
public class AInterface : ITestInterface<A>
{
public A GetSomething()
{
return new A();
}
}
public class B : BaseClass
{
public override string IAM => "I AM TYPE B";
}
public class BInterface : ITestInterface<B>
{
public B GetSomething()
{
return new B();
}
}
Class we want to resolve:
public interface ISomeClass
{
void DoSomething();
}
public class SomeClass<T> : ISomeClass where T : BaseClass
{
private readonly IEnumerable<ITestInterface<T>> _testInterfaces;
public SomeClass(IEnumerable<ITestInterface<T>> testInterfaces)
{
_testInterfaces = testInterfaces;
}
public void DoSomething()
{
foreach (var t in _testInterfaces)
{
var something = t.GetSomething();
Console.WriteLine(something.IAM);
}
}
}
And finally, Autofac configuration:
var builder = new ContainerBuilder();
builder
.RegisterType<SomeClass<BaseClass>>()
.AsSelf();
builder
.RegisterType<AInterface>()
.As<ITestInterface<BaseClass>>();
builder
.RegisterType<BInterface>()
.As<ITestInterface<BaseClass>>();
builder
.RegisterType<SomeClass<BaseClass>>()
.As<ISomeClass>();
var container = builder.Build();
var x = container.Resolve<ISomeClass>();
x.DoSomething();
Outputs:
I AM TYPE A
I AM TYPE B
Hope this helps someone in the future.
RegisterGeneric should work fine :
builder.RegisterType<TestImplementationA>()
.As<ITestInterface<A>>();
builder.RegisterType<TestImplementationB>()
.As<ITestInterface<B>>();
builder.RegisterGeneric(typeof(SomeClass<>))
.As(typeof(ISomeClass<>));
or
builder.RegisterType<TestImplementationA>()
.As<ITestInterface<A>>();
builder.RegisterType<TestImplementationB>()
.As<ITestInterface<B>>();
builder.RegisterGeneric(typeof(SomeClass<>))
.AsSelf();
You will find below a working sample :
public interface ISomeClass<T> where T : class
{
Int32 Count { get; }
}
public class SomeClass<T> : ISomeClass<T> where T : class
{
private readonly IEnumerable<ITestInterface<T>> _testInterfaces;
public SomeClass(IEnumerable<ITestInterface<T>> testInterfaces)
{
_testInterfaces = testInterfaces;
}
public Int32 Count
{
get
{
return this._testInterfaces.Count();
}
}
}
public interface ITestInterface {}
public interface ITestInterface<T> : ITestInterface { }
public class A { }
public class B { }
public class TestImplementationA : ITestInterface<A> { }
public class TestImplementationB : ITestInterface<B> { }
class Program
{
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<TestImplementationA>()
.As<ITestInterface<A>>()
.As<ITestInterface>();
builder.RegisterType<TestImplementationB>()
.As<ITestInterface<B>>()
.As<ITestInterface>();
builder.RegisterGeneric(typeof(SomeClass<>))
.As(typeof(ISomeClass<>));
IContainer container = builder.Build();
var x = container.Resolve<ISomeClass<A>>();
Console.WriteLine(x.Count);
var z = container.Resolve<IEnumerable<ITestInterface>>();
}
}

Injecting a list of dependencies with multiple interfaces in autofac

I have this class where I'm trying to inject a list of qualifying objects:
public class BlingDispatcher : IBlingDispatcher
{
readonly IEnumerable<IDomainEventHandler> _domainEventHandlers;
#region IBlingDispatcher Members
public BlingDispatcher(IEnumerable<IDomainEventHandler> domainEventHandlers)
{
_domainEventHandlers = domainEventHandlers;
}
}
Classes like this get injected here and work great:
public class NotifyFrontEndSomethingHappened : IDomainEventHandler<SomethingHappened>
{
private readonly IFrontEndNotifier _frontEndNotifier;
public NotifyFrontEndAfterSomethingHappened(IFrontEndNotifier frontEndNotifier)
{
_frontEndNotifier = frontEndNotifier;
}
}
Classes like this do not:
public class NotifyFrontEndAfterEvent : IDomainEventHandler<SomethingHappened>,
IDomainEventHandler<SomethingElseHappened>,
IDomainEventHandler<MoreThingsHappened>,
IDomainEventHandler<AndYetMoreThings>
{
readonly IFrontEndNotifier _frontEndNotifier;
public void Handle(SomethingHappened #event)
{
_frontEndNotifier.Notify(#event, #event.CommanderId);
}
...
}
How can I get classes with multiple interfaces to be injected by autofac as well?
EDIT
More information:
public interface IDomainEventHandler
{
}
public interface IDomainEventHandler<in T> : IBlingHandler<T>, IDomainEventHandler
{
}
public interface IBlingHandler<in T>
{
void Handle(T #event);
}
Registering like this in bootstapper:
container.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(x => x.GetInterfaces().Any(i => i.Name.StartsWith("IBlingHandler")))
.AsImplementedInterfaces();

Structuremap interception for registry scanned types

I have a ASP MVC 4 app that uses Structuremap. I'm trying to add logging to my application via Structuremap interception.
In a Registry, I scan a specific assembly in order to register all of it's types with the default convention:
public class ServicesRegistry : Registry
{
public ServicesRegistry()
{
Scan(x =>
{
x.AssemblyContainingType<MyMarkerService>();
x.WithDefaultConventions();
});
}
}
The interceptor:
public class LogInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var watch = Stopwatch.StartNew();
invocation.Proceed();
watch.Stop();//log the time
}
}
I can add the interceptor for one specific plugin type like this:
var proxyGenerator = new ProxyGenerator();
container.Configure(x => x.For<IServiceA>().Use<ServiceA>().DecorateWith(instance => proxyGenerator.CreateInterfaceProxyWithTarget(instance, new LogInterceptor())));
but I want to make structuremap create logging proxies for all the types that were scanned in the registry.
Is there a way to achieve this?
It doesn't look like there's an easy extension point for this, but I got it working with a fairly decent solution using a custom convention. In order to help you understand the decisions I made I'll walk you through a few steps (skipping the many, many missteps I made on my way).
First lets look at the DefaultConvention which you are already using.
DefaultConvention:
public class DefaultConventionScanner : ConfigurableRegistrationConvention
{
public override void Process(Type type, Registry registry)
{
if (!TypeExtensions.IsConcrete(type))
return;
Type pluginType = this.FindPluginType(type);
if (pluginType == null || !TypeExtensions.HasConstructors(type))
return;
registry.AddType(pluginType, type);
this.ConfigureFamily(registry.For(pluginType, (ILifecycle)null));
}
public virtual Type FindPluginType(Type concreteType)
{
string interfaceName = "I" + concreteType.Name;
return Enumerable.FirstOrDefault<Type>((IEnumerable<Type>)concreteType.GetInterfaces(), (Func<Type, bool>)(t => t.Name == interfaceName));
}
}
Pretty simple, we get the type and interface pairs and check to make sure they have a constructor, if they do we register them. It would be nice to just modify this so that it calls DecorateWith, but you can only call that on For<>().Use<>(), not For().Use().
Next lets look at what DecorateWith does:
public T DecorateWith(Expression<Func<TPluginType, TPluginType>> handler)
{
this.AddInterceptor((IInterceptor) new FuncInterceptor<TPluginType>(handler, (string) null));
return this.thisInstance;
}
So this creates a FuncInterceptor and registers it. I spent a fair bit of time trying to create one of these dynamically with reflection before deciding it would just be easier to make a new class:
public class ProxyFuncInterceptor<T> : FuncInterceptor<T> where T : class
{
public ProxyFuncInterceptor() : base(x => MakeProxy(x), "")
{
}
protected ProxyFuncInterceptor(Expression<Func<T, T>> expression, string description = null)
: base(expression, description)
{
}
protected ProxyFuncInterceptor(Expression<Func<IContext, T, T>> expression, string description = null)
: base(expression, description)
{
}
private static T MakeProxy(T instance)
{
var proxyGenerator = new ProxyGenerator();
return proxyGenerator.CreateInterfaceProxyWithTarget(instance, new LogInterceptor());
}
}
This class just makes it easier to work with when we have the type as a variable.
Finally I've made my own Convention based on the Default convention.
public class DefaultConventionWithProxyScanner : ConfigurableRegistrationConvention
{
public override void Process(Type type, Registry registry)
{
if (!type.IsConcrete())
return;
var pluginType = this.FindPluginType(type);
if (pluginType == null || !type.HasConstructors())
return;
registry.AddType(pluginType, type);
var policy = CreatePolicy(pluginType);
registry.Policies.Interceptors(policy);
ConfigureFamily(registry.For(pluginType));
}
public virtual Type FindPluginType(Type concreteType)
{
var interfaceName = "I" + concreteType.Name;
return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
}
public IInterceptorPolicy CreatePolicy(Type pluginType)
{
var genericPolicyType = typeof(InterceptorPolicy<>);
var policyType = genericPolicyType.MakeGenericType(pluginType);
return (IInterceptorPolicy)Activator.CreateInstance(policyType, new object[]{CreateInterceptor(pluginType), null});
}
public IInterceptor CreateInterceptor(Type pluginType)
{
var genericInterceptorType = typeof(ProxyFuncInterceptor<>);
var specificInterceptor = genericInterceptorType.MakeGenericType(pluginType);
return (IInterceptor)Activator.CreateInstance(specificInterceptor);
}
}
Its almost exactly the same with one addition, I create an interceptor and interceptorType for each type we register. I then register that policy.
Finally, a few unit tests to prove it works:
[TestFixture]
public class Try4
{
[Test]
public void Can_create_interceptor()
{
var type = typeof (IServiceA);
Assert.NotNull(new DefaultConventionWithProxyScanner().CreateInterceptor(type));
}
[Test]
public void Can_create_policy()
{
var type = typeof (IServiceA);
Assert.NotNull(new DefaultConventionWithProxyScanner().CreatePolicy(type));
}
[Test]
public void Can_register_normally()
{
var container = new Container();
container.Configure(x => x.Scan(y =>
{
y.TheCallingAssembly();
y.WithDefaultConventions();
}));
var serviceA = container.GetInstance<IServiceA>();
Assert.IsFalse(ProxyUtil.IsProxy(serviceA));
Console.WriteLine(serviceA.GetType());
}
[Test]
public void Can_register_proxy_for_all()
{
var container = new Container();
container.Configure(x => x.Scan(y =>
{
y.TheCallingAssembly();
y.Convention<DefaultConventionWithProxyScanner>();
}));
var serviceA = container.GetInstance<IServiceA>();
Assert.IsTrue(ProxyUtil.IsProxy(serviceA));
Console.WriteLine(serviceA.GetType());
}
[Test]
public void Make_sure_I_wait()
{
var container = new Container();
container.Configure(x => x.Scan(y =>
{
y.TheCallingAssembly();
y.Convention<DefaultConventionWithProxyScanner>();
}));
var serviceA = container.GetInstance<IServiceA>();
serviceA.Wait();
}
}
}
public interface IServiceA
{
void Wait();
}
public class ServiceA : IServiceA
{
public void Wait()
{
Thread.Sleep(1000);
}
}
public interface IServiceB
{
}
public class ServiceB : IServiceB
{
}
There's definitely room for some clean up here (caching, make it DRY, more tests, make it easier to configure) but it works for what you need and is a pretty reasonable way of doing it.
Please ask if you have any other questions about it.

Define custom conversion for structuremap to register Commands, CommandHandlers automatically

I'm using CQRS pattern in my recent project, so I defined some Commands that I call them CommandParameter and CommandHandlers.
For CommandParameters I have these Classes and Interfaces:
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : IAggregateRoot,ICommandParameter
where T : ModelEntitySuperType, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T>
where T : class, new()
{
}
And for CommandHandlers I defined these Classes and Interfaces:
public interface ICommandHandler<TCommandParameter>
where TCommandParameter :ICommandParameter
{
void Handle(TCommandParameter parameter);
string CommandCode { get; }
}
public class InsertCommandHandler<TCommandParameter, TEntity>
: ICommandHandler<TCommandParameter>
where TCommandParameter : BaseEntityCommandParameter<TEntity>, new()
where TEntity : ModelEntitySuperType, IAggregateRoot, new()
and I used them to make appropriate CommandParameters and CommandHandlers for each Entity for example for Order I have:
public class OrderInsertCommandParameter:InsertCommandParameter<Order>
{
}
public class OrderInsertCommandHandler
: InsertCommandHandler<OrderInsertCommandParameter, Order>
{
private readonly IUnitOfWorkFactory _factory;
public OrderInsertCommandHandler(IUnitOfWorkFactory factory,
IRepository<Order> repository)
: base(repository)
{
_factory = factory;
}
public override void Handle(OrderInsertCommandParameter parameter)
{
var uow = _factory.Create();
parameter.Entity.OrderCreationTime = DateTime.Now;
base.Handle(parameter);
uow.Commit();
}
}
I want to register these CommandParameters and appropriate CommandHandlers using structuremap automatically, How could I define a custom Conversion to do this?
The following should do the trick:
container.Configure(r =>
{
r.Scan(s =>
{
s.Assembly(typeof(ICommandHandler<>).Assembly);
s.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
});
});

Categories