I've literally just started using the Unity Application Blocks Dependency Injection library from Microsoft, and I've come unstuck.
This is my IoC class that'll handle the instantiation of my concrete classes to their interface types (so I don't have to keep called Resolve on the IoC container each time I want a repository in my controller):
public class IoC
{
public static void Intialise(UnityConfigurationSection section, string connectionString)
{
_connectionString = connectionString;
_container = new UnityContainer();
section.Configure(_container);
}
private static IUnityContainer _container;
private static string _connectionString;
public static IMovementRepository MovementRepository
{
get { return _container.Resolve<IMovementRepository>(); }
}
}
So, the idea is that from my Controller, I can just do the following:
_repository = IoC.MovementRepository;
I am currently getting the error:
Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.
Now, I'm assuming this is because my mapped concrete implementation requires a single string parameter for its constructor. The concrete class is as follows:
public sealed class MovementRepository : Repository, IMovementRepository
{
public MovementRepository(string connectionString) : base(connectionString) { }
}
Which inherits from:
public abstract class Repository
{
public Repository(string connectionString)
{
_connectionString = connectionString;
}
public virtual string ConnectionString
{
get { return _connectionString; }
}
private readonly string _connectionString;
}
Now, am I doing this the correct way? Should I not have a constructor in my concrete implementation of a loosely coupled type? I.e. should I remove the constructor and just make the ConnectionString property a Get/Set so I can do the following:
public static IMovementRepository MovementRepository
{
get
{
return _container.Resolve<IMovementRepository>(
new ParameterOverrides
{
{
"ConnectionString", _connectionString
}
}.OnType<IMovementRepository>() );
}
}
So, I basically wish to know how to get my connection string to my concrete type in the correct way that matches the IoC rules and keeps my Controller and concrete repositories loosely coupled so I can easily change the DataSource at a later date.
EDIT 09:52:
Just to re-iterate what I'm after. I want to know the correct way to pass the ConnectionString or an IRepositoryConfiguration object (prefer that idea, thanks Mc) to a concrete class from Unity. I'm not too fussed on what I pass, just how I pass it whilst maintaining loose coupling.
I didnt use Unity but I have used configuration objects in these situations. For example you can write your code like this
So you can register IRepositoryConfiguration and Unity will resolve your configuration objects. Also you can add extra parameters in this approach easily.
Update
I think it is ok to have a constructor that accepts IRepositoryConfiguration object in your concrete classes(abstract repository and MovementRepository). Becase they are implementations details and concrete implementations of IMovementRepository.so they need to know connection string.
Setter or Constructor Injection
I prefer constructor injection over setter injection. I think constructor injection leads more discoverable APIs. in Constructor injection as soon as when you want to instantiate object, you see what an object needs to work but in Setter injection you must learn which property to set to use API. For detailed information you can read Constructor ve Setter Injection
You can configure the unity container for this:
in XLM that would probably be something like this:
or wrap the connectionstring as mcaaltuntas points out.
I ll add another way :)
You can use Injection parameters that get passed into the constructor when you register a type. This way you can still use constructor injection.
Probably the most straight forward way to do this is to set up a constructor section for your mapped type in the unity configuration and inside the constructor section have a parameter element for the connection string that passes in a name value for a connection string you have defined in the connectionStrings section of your web configuration.
Inside your constructor code for the Repository class, have some code that uses the name value of the connection string to get the full connection string from the connectionStrings section.
EDIT:
Here's an example for you using Unity 2.0
In your web.config, specify the connection string and a mapping for unity to map an
IRepository<T>
to aSqlRepository<T>
. Based on your other questions, we'll assume thatIRepository<T>
is in your model project andSqlRepository<T>
is in your DAL project.Now for the
IRepository<T>
interface in the model project. In this example, I'm also going to be using LINQ to SQL to return objects from the SQL DatabaseAnd the
SQLRepository<T>
class in the DAL projectLet's also use a custom controller factory to allow unity to return controllers for us. This way, unity will inject any dependencies that the controllers have
In global.asax
And Here's a controller example.
PageSize
might be defined on a base controller or on the controller as a property.When the customers list controller action is invoked, unity will correctly instantiate an instance of
SqlRepository<Customer>
for the controller and inject this into the constructor. the connectionString string used forSqlRepository<T>
is set in the unity configuration and is passed into the constructor for a typedSqlRepository<T>
.