I spent some time on documentation on dependency injection and IoC, but I did not find a solution for my problem.
My problem is creating objects when using the dependency container in the sense that it creates a dependency on the constructor arguments. In almost all the examples I came across, the constructors of specific classes have no arguments. This makes everything pretty βsimple." Hence my question.
Take an example: I need to load some data from two sources A and B. Source A contains data in a different format; e.g. csv and xml. We do not need to indicate such a thing for source B.
Here is some code (note that I simplified the code as much as I could to illustrate my point):
using System.Net;
using System.IO;
using System.Reflection;
namespace Question
{
class Program
{
static void Main(string[] args)
{
DependencyContainer container1 = GetContainer1();
IClient client1 = container1.Resolve<IClient>("xml");
User user1 = new User(client1);
user1.run();
DependencyContainer container2 = GetContainer2();
IClient client2 = container2.Resolve<IClient>();
User user2 = new User(client2);
user2.run();
}
public static DependencyContainer GetContainer1()
{
DependencyContainer container = new DependencyContainer();
container.Register<IClient, ClientA>();
return container;
}
public static DependencyContainer GetContainer2()
{
DependencyContainer container = new DependencyContainer();
container.Register<IClient, ClientB>();
return container;
}
}
public class User
{
private readonly IClient _Client;
public User(IClient client)
{
_Client = client;
}
public void run()
{
string address = _Client.getAddress();
string data = _Client.getData(address);
_Client.writeData(data);
}
}
public interface IClient
{
string getAddress();
string getData(string adress);
void writeData(string data);
}
public class ClientA : IClient
{
private readonly string _FileType;
public ClientA(string fileType)
{
_FileType = fileType;
}
public string getAddress()
{
return "addressOfFileContainingData." + _FileType;
}
public string getData(string address)
{
string data = string.Empty;
using (WebClient client = new WebClient())
{
data = client.DownloadString(address);
}
return data;
}
public void writeData(string data)
{
string localAddress = "C:/Temp/";
using (StreamWriter writer = new StreamWriter(localAddress))
{
writer.Write(data);
}
}
}
public class ClientB : IClient
{
public ClientB()
{
}
public string getAddress()
{
return "addressOfFileContainingData";
}
public string getData(string address)
{
string data = string.Empty;
using (WebClient client = new WebClient())
{
data = client.DownloadString(address);
}
return data;
}
public void writeData(string data)
{
string localAddress = "C:/Temp/";
using (StreamWriter writer = new StreamWriter(localAddress))
{
writer.Write(data);
}
}
}
public class DependencyContainer
{
private Dictionary<Type, Type> _Map = new Dictionary<Type, Type>();
public void Register<TypeToResolve, ResolvedType>()
{
_Map.Add(typeof(TypeToResolve), typeof(ResolvedType));
}
public T Resolve<T>(params object[] constructorParameters)
{
return (T)Resolve(typeof(T), constructorParameters);
}
public object Resolve(Type typeToResolve, params object[] constructorParameters)
{
Type resolvedType = _Map[typeToResolve];
ConstructorInfo ctorInfo = resolvedType.GetConstructors().First();
object retObject = ctorInfo.Invoke(constructorParameters);
return retObject;
}
}
}
, , . , :
IClient client = container.Resolve<IClient>("xml");
IClient client = container.Resolve<IClient>();
. ( User ) , . ! , - . , . , ClientA , , , .
, :
ClientA. , ? , ?
, ClientA ClientB , .
.