为了帮助提高我对IOC的理解以及如何使用它,我想创建所有三种IOC技术的示例:构造函数注入,Setter注入和接口注入,而不必使用第三方框架。我想我有一个构造函数注入的基本示例,但在使用setter和接口注入方面苦苦挣扎。
您将如何从头开始处理编写接口和setter注入?
这是我的想法,如果我走在正确的轨道上,请告诉我。
接口注入:
Setter注射:
public class Program
{
static void Main(string[] args)
{
//
//instead of doing this:
//
//ICreditCard creditCard = new Visa();
//var customer = new Customer(creditCard);
//customer.Charge();
var resolver = new Resolver();
//map the types in the container
resolver.Register<Customer, Customer>();
resolver.Register<ICreditCard, Visa>();
//because the customer constructor has an ICreditCard parameter
//our container will automatically instantiate it recursively
var customer = resolver.Resolve<Customer>();
customer.Charge();
}
}
public interface ICreditCard
{
string Charge();
}
public class Visa : ICreditCard
{
public string Charge()
{
return "Charging Visa";
}
}
public class MasterCard : ICreditCard
{
public string Charge()
{
return "Charging MasterCard";
}
}
public class Customer
{
private readonly ICreditCard _creditCard;
public Customer(ICreditCard creditCard)
{
this._creditCard = creditCard;
}
public void Charge()
{
_creditCard.Charge();
}
}
public class Resolver
{
private Dictionary<Type, Type> dependencyMap = new Dictionary<Type, Type>();
public T Resolve<T>()
{
return (T) Resolve(typeof (T));
}
private object Resolve(Type typeToResolve)
{
Type resolvedType = null;
try
{
resolvedType = dependencyMap[typeToResolve];
}
catch
{
throw new Exception(string.Format("could not resolve type {0}", typeToResolve.FullName));
}
var firstConstructor = resolvedType.GetConstructors().First();
var constructorParameters = firstConstructor.GetParameters();
if (constructorParameters.Count() == 0)
return Activator.CreateInstance(resolvedType);
IList<object> parameters = constructorParameters.Select(parameterToResolve => Resolve(parameterToResolve.ParameterType)).ToList();
return firstConstructor.Invoke(parameters.ToArray());
}
public void Register<TFrom, TTo>()
{
dependencyMap.Add(typeof (TFrom), typeof (TTo));
}
}
答案 0 :(得分:3)
这是你想要的吗?
class Container
{
class Registration
{
public Type RegistrationType;
public Func<Container, object> Resolver;
}
List<Registration> registrations = new List<Registration>();
public object Resolve(Type type)
{
return registrations
.First(r => type.IsAssignableFrom(r.RegistrationType))
.Resolver(this);
}
public T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
public void Register<T>(Func<Container, T> registration) where T : class
{
registrations.Add(new Registration()
{
RegistrationType = typeof(T),
Resolver = registration
});
}
}
用法:
interface IDependency
{
string GetName();
}
class ConcreteDependency : IDependency
{
public string GetName()
{
return "Concrete Dependency";
}
}
class ConstructorExample
{
readonly IDependency dependency;
public ConstructorExample(IDependency dependency)
{
this.dependency = dependency;
}
public string GetString()
{
return "Consumer of " + dependency.GetName();
}
}
class SetterExample
{
public IDependency Dependency { get; set; }
public string GetString()
{
return "Consumer of " + Dependency.GetName();
}
}
[TestMethod]
public void MyTestMethod()
{
var container = new Container();
container.Register<IDependency>(c => new ConcreteDependency());
container.Register(c => new ConstructorExample(c.Resolve<IDependency>()));
container.Register(c => new SetterExample() { Dependency = c.Resolve<IDependency>() });
var constructor = container.Resolve<ConstructorExample>();
Assert.AreEqual("Consumer of Concrete Dependency", constructor.GetString());
var setter = container.Resolve<SetterExample>();
Assert.AreEqual("Consumer of Concrete Dependency", setter.GetString());
}
如果您想获得更高级的内容,我建议您获取以下任意内容:SimpleInjector,Autofac,Ninject,StructureMap。