Unity

  • Thread starter Thread starter Peter Morris
  • Start date Start date
P

Peter Morris

I have an instance of a business object, which belongs to a specific "object
space"

var objectSpace = new ObjectSpace();
var location = objectSpace.(etc).GetByName("My house");

Now I have a service which should work on the location

var publishService = unity.Resolve<IPublishService>();
publishService.Publish(location);

but the publish service also needs a reference to the objectSpace. Adding
the object space parameter to the parameters seems like a hack, using an
instance-per-request and setting publishService.ObjectSpace seems like it
might be easy to forget.

Is there a way to do something like

var publishService = unity.Resolve<IPublishService>(objectSpace);

Thanks
 
Could you possibly do something like the folowing in your
IPublishService/PublishServiceImpl

interface IPublishService
{
IPublishService SetObjectSpace(ObjectSpace os);
IPublishService And { get; }
}

which would enable a fluent interface such as ...

publishService.SetObjectSpace(objectSpace).And.Publish(location);

of course this does not make it impossible for anyone to call
Publish(location) without first making a call to SetObjectSpace, but you
could always enforce this in Publish, for example:

public void Publish(object location)
{
// if we don't have an object space reference throw an
ObjectSpaceNotSetException();
}

Notice as well that I cannot tell what type location is supposed to be, this
is because you have used the following non-intuitive code

var location = objectSpace.(etc).GetByName("My house");

in which the member GetByName(string) gives no indication of what type is
returned, I personally think this is a bad use of the var keyword, in fact
nothing is gained by using it and as it stands it only serves to confuse the
reader.

There is an overload Resolve<T>(string), but this is only used for
retrieving named instances. It would be possible to overload this yourself,
using extension methods, for example

public static class IUnityContainerExtensions
{
public static T Resolve<T>(this IUnityContainer container, ObjectSpace
space)
{
T resolved = container.Resolve<T>();
resolved.ObjectSpace = space;
return resolved;
}
}

For what it's worth :o)
 
Hi Bill
publishService.SetObjectSpace(objectSpace).And.Publish(location);

I think people would still go straight for publishService.Publish, besides I
wouldn't want to change the interface just to make Unity's use of it
different.
var location = objectSpace.(etc).GetByName("My house");

The type of location was not important, which is why I also used (etc), I'm
just saving space by excluding non-important info :-)
public static class IUnityContainerExtensions
{
public static T Resolve<T>(this IUnityContainer container, ObjectSpace
space)
{
T resolved = container.Resolve<T>();
resolved.ObjectSpace = space;
return resolved;
}
}

I'll mull this over a bit, not sure about it yet. I was hoping there would
be a way of specifying additional runtime parameters for the service's
constructor in my code, maybe something like

var constructorParameters = new { ObjectSpace = existingObjectSpace };
MyUnityContainer.Resolve<IPublishingService>(constructorParameters);

I don't know, there just seems to be something "missing".
 
I think I am just going to go for

void Publish(IEcoServiceProvider serviceProvider, Location location)

would be nice not to have to pass a service provider with every call that
needs one, but I will try it this way for a while before forming my final
opinion :-)

Thanks for the info!
 
In the end I descended from UnityContainer and added

ResolveEcoService<T>(IEcoServiceProvider ecoServiceProvider)
where T : IEcoSpaceService
{
var result = Resolve<T>();
(result as IEcoSpaceService).ServiceProvider = ecoServiceProvider;
return result;
}
 
Back
Top