with the service bus/event aggregator model you would pass DTOs to the
View/UI. This is also called the View Model. Each screen has it's own
set of DTO's. mapping the Domain model to the View Model can be
accomplished with a framework like AutoMapper.
Unfortunately I haven't found a spike for a full blown service bus/
event aggregator. StoryTeller has all the moving parts for the event
aggregator. There are many pieces on the web about how to handle
messaging. with RSB it would look something like this
within a presenter you would send the message
bus.Send(new MyMessage {[properties]});
then you would have a consumer to process that message. here is a
basic example utilizing AutoMapper
class MyMessageConsumer : ConsumerOf<MyMessage>
{
public class MyMessageConsumer(ISession session, IMappingEngine
mapper, IServiceBus bus) {...}
public void Consume(MyMessage message)
{
var entity = session.Get<Entity>(message.Id);
var dto = mapper.Map<Entity, DTO>(entity);
bus.Reply(new MyResponse{ Data = dto});
}
}
the reply is sent back to the source, in this case our rich client.
where MyResponse will be processed
class MyResponseConsumer : ConsumerOf<MyResponse>
{
public class MyResponseConsumer(IEventAggregator aggregator) {...}
public void Consume(MyResponse message)
{
aggregator.Handle(message.Dto);
}
}
this is where the EventAggregator takes over. It would know that it's
consuming a type of DTO and notify all the instantiated presenters to
update their view.
All of this is happening in background threads, so the event
aggregator uses a SynchronizationContext to allow the UI to update on
the main thread. That is easy enough to follow from StoryTellers code
base.
I know with Rhino (and I believe for the other service buses)
consumers/handlers are transient (or not singletons). Using the IoC of
you choice you can inject the current session into the consumer.
now this is the simplest example. You can also get into scenarios
where the consumers are Sagas. A Saga coordinates multiple
asynchronous events. Ayende and Udi have some posts about this Sagas.
as for managing the session here is how I manage it with
Rhino.ServiceBus. again I believe there is a concept of IMessageModule
in all the service bus frameworks. I'm just not aware of there name.
namespace StockBook.Core.Infrastructure.Messaging
{
public class NhibernateMessageModule : IMessageModule
{
private readonly ISessionFactory Factory;
public NhibernateMessageModule(ISessionFactory factory)
{
Factory = factory;
}
public void Init(ITransport transport)
{
transport.MessageArrived += OpenSession;
transport.MessageProcessingCompleted += CloseSession;
}
public void Stop(ITransport transport)
{
transport.MessageArrived -= OpenSession;
transport.MessageProcessingCompleted -= CloseSession;
}
private bool OpenSession(CurrentMessageInformation arg)
{
CurrentSessionContext.Bind(Factory.OpenSession());
return false;
}
private void CloseSession(CurrentMessageInformation arg1,
Exception arg2)
{
var session = CurrentSessionContext.Unbind(Factory);
if (session == null) return;
session.Dispose();
}
}
}
the CurrentSessionContext singleton is part of core NHibernate, no
need for NH Addins. the common contexts are WebSessionContext,
ThreadStaticSessionContext and MappedSessionContext. web is self
explaintory:) ThreadStatic is meant for use with a single
SessionFactory. If you have more than 1 session factory the Mapped
context will track which session belongs to which factory. This
requires that each Factory has a name.
my NH configuration looks like this
namespace StockBook.Core.Infrastructure.Facility
{
public class NhibernateForServiceFacility : AbstractFacility
{
protected override void Init()
{
var configuration = Fluently
.Configure()
.Database(MsSqlConfiguration
.MsSql2000
.AdoNetBatchSize(20)
.ProxyFactoryFactory(typeof
(ProxyFactoryFactory).AssemblyQualifiedName)
.ConnectionString(builder =>
builder.FromConnectionStringWithKey("StockBook")))
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<Category>())
.ExposeConfiguration(cfg => cfg
.SetProperty
(Environment.PrepareSql, true.ToString())
.SetProperty
(Environment.CurrentSessionContextClass, typeof
(ThreadStaticSessionContext).AssemblyQualifiedName))
.BuildConfiguration();
var factory = configuration.BuildSessionFactory();
Kernel.AddComponentInstance<Configuration>(configuration);
Kernel.AddComponentInstance<ISessionFactory>(factory);
Kernel.Register(Component
.For<ISession>()
.LifeStyle.Is(LifestyleType.Transient)
.UsingFactoryMethod(k =>
k.Resolve<ISessionFactory>().GetCurrentSession()));
}
}
}
this uses Castle Windsor, so the symantics would be different for your
container of choice. I'm using Fluent NH to build the configuration.
The key features are Defining the CurrentSessionContext. I'm using
Castle's factory facility to resolve the current session.
in the end you will end up with *many* small classes a ViewModel with
a unique POCO for each view. A message for each action. A consumer/
saga for the message. A handler for each published UI event from the
UI aggregator.
On Oct 21, 8:57 am, Everett Muniz <
everettmu...@gmail.com> wrote:
> :-) with that kind of recommendation I'll be sure to check it out
>
> On Wed, Oct 21, 2009 at 8:56 AM, José F. Romaniello <
>
>
joseromanie...@gmail.com> wrote:
> > Did you see the nhibernate session handling in this class (from the chinook
> > sample):
>
> >
http://code.google.com/p/unhaddins/source/browse/trunk/Examples/uNHAd...
>
> > <
http://code.google.com/p/unhaddins/source/browse/trunk/Examples/uNHAd...>Checkout
> > the AOP way, it is really a "Manna from heaven".
>
> > 2009/10/21 Everett Muniz <
everettmu...@gmail.com>
>
> > Jason, thanks for taking the time to flesh out that approach! I've
> >> actually been spelunking in StoryTeller just in the last week. I've even
> >> spiked the core bits of Jeremy's approach for our situation and I like what
> >> I'm seeing. I'm still struggling a bit to map the function pieces to the
> >> names Jeremy has chosen but until I grok it a bit better I'm sticking with
> >> what's represented in the code base.
> >> I don't have any experience with implementing one of the service bus
> >> implementations you mention but that's not necessarily a deal breaker. I
> >> spent some time with the non-aop conversation example from the unhAddins
> >> project last night and there are several "moving parts" to the CpBT
> >> implementation. I guess my point is that I'm looking at a learning curve
> >> regardless of the direction we choose. I'd prefer not to have to get quite
> >> so intimate with NHibernate as the CpBT implementation seems to require but
> >> it may be unavoidable.
>
> >> Can you point me at any solid reference implementations of the kind of
> >> architecture you're describing? I mean something that's using the service
> >> bus concept.
>