Unity and injection

P

Peter Morris

Hi all

I hope there is someone out there who is familiar with Unity? I have a
question...

//A service that needs to be implemented
public interface IMyService
{
void OutputString(string text);
}

//An implementation of this service
public class MyServiceImpl : IMyService
{
public void OutputString(string text)
{
Console.WriteLine(text);
}
}

//Something I don't want UNITY to create
public class DataContext
{
public string ID;
}

//A class that requires the service + the data context
public class Person
{
readonly DataContext DataContext;
readonly IMyService MyService;

public Person(DataContext dataContext, IMyService myService)
{
DataContext = dataContext;
MyService = myService;
}

public void DoIt(string text)
{
MyService.OutputString(text);
}
}


//Now the code to set up my container...

Container = new UnityContainer();
Container.RegisterType<IMyService, MyServiceImpl>(new
ContainerControlledLifetimeManager());


What I want to do now is to use my container to create an instance of
Person. I want Unity to pass in the IMyService, but I want to pass in the
DataContext myself...


DataContext dc = new DataContext();
dc.ID = "My Data Context";

//How do I send in my instance of DataContext?
Person p = Container.Resolve<Person>();
p.DoIt("hello");


Unity will create the DataContext instance itself. I want something like...

Person p = Container.Resolve<Person>(dc);

I know this exact code is not possible or I wouldn't be posting. What I
want to know is, is there a way I can pass in specific values to be used
when injecting dependencies?



Thanks
 
M

miher

Hi,

You can ask unity to use a given instance when resolving a type by
registering it.
Container .RegisterInstance<DataContext >(dc);
After this unity will use the instance 'dc' every time when a DataContext is
needed to be resolved.

If You would like to apply this only for the Person class, You can configure
injection for it.
Container .Configure<InjectedMembers>().
ConfigureInjectionFor<Person>(
new InjectionConstructor(
dc,
new ResolvedParameter<IMyService>()
) );
This will make unity to use the constructor with the given parameters when
asked to resolve a Person, and will use the given 'dc' instance and a
resolved IMyService as parameters.

Hope You find this useful.
-Zsolt
 
P

Peter Morris

Hi

Thanks for the reply. It's not quite what I want though. I don't want a
singleton, nor a single context for Person and a different one for Company.
What I want to achieve is something like this

DataContext c1 = .......
DataContext c2 = .......

Person p1 = Container.Resolve<Person>(c1);
Person p2 = Container.Resolve<Person>(c2);


Where DataContext could be thought of as an object cache, a unit of work, a
transaction, or something similar; something where the calling method owns a
context which must be passed onto the constructor of the class being
instantiated.

Is it possible to do that?


Regards
 
M

miher

Hi,

You can try any of the following:

-Change the Person constructor parameters to only the DataContext, then
create Your Person object "by hand", after that use BuildUp to inject other
dependencies.

- Use the StaticFactoryExtension, which lets You define a factory for given
types.

Hope any of these helps.
-Zsolt
 
P

Peter Morris

Hi again
-Change the Person constructor parameters to only the DataContext, then
create Your Person object "by hand", after that use BuildUp to inject
other dependencies.

The changes I intend to make will be to an object persistence framework. At
the moment there is a "recreate from database" kind of constructor

public MyClass(IContent content)
{
}

and a "create from scratch" constructor

public MyClass(IEcoServiceProvider serviceProvider)
{
}


Now I can either change the constructors, in which case I need to add
additional parameters, or I can use dependency properties or an injection
method. Whichever approach I take I will still need to pass a specific
instance for the one parameter.


- Use the StaticFactoryExtension, which lets You define a factory for
given types.

As I am going to extend a framework the types will be unknown by the code.
It's only a 2 specific points in the framework where I would like to wire in
the container, and will need to pass on the original parameter as part of
the construction of the instance.

Any more thoughts?
 
P

Peter Morris

Here's a better example of what I need

var objectSpace1 = new ObjectSpace();
var objectSpace2 = new ObjectSpace();

var person1 = Container.Resolve<Person>(objectSpace1);
var person2 = Container.Resolve<Person>(objectSpace2);

public Person(
ObjectSpace objectSpace,
ILoggingService loggingService)
{
}

All of my business classes will expect an ObjectSpace instance as their
first parameter. Imagine there are hundreds of these classes, I obviously
don't want to have to configure them. Is there any way to do this?
 
M

miher

Hi,

As i know if You have two kind of dependencies(1 group that You want to
resolve by hand, another that You would like Unity to resolve), You might
need to separate those, so for example You manually inject group1 the use
BuildUp to make Unity finish the job. However i see that You have
contructor with both kind of parameters and You can't /don't want to change
it.
Anyhow from the code You posted its seems to me that before every resolve
You need to specify the current ObjectSpace instance somehow. As i see that
if You do that by a parameter or by -for example- registering the current
instance for the type before resolve is mostly syntax difference.
So to make it short i'm sorry but i can't give "better" solution for this,
than the ones i posted before.
I wish You to find a solution suitable for Your needs.
-Zsolt
 
P

Peter Morris

My minimum requirement is the ObjectSpace parameter. I can use a
DependencyAttribute on some service properties to get unity to fix them up
but I don't like to have public service properties on my classes. I could
also have an InjectionMethodAttribute on a method and fix them up in there,
but one of the reasons I like constructor injection is that when I change my
dependencies my test code will refuse to compile until I resolve the
changes.
 
P

Peter Morris

I found the Unity forum yesterday (I wish MS would standardise on whether
they use newsgroups or forums, it makes them much harder to find), someone
on there says that what I want is not possible.

Thanks for your help though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top