自定义IOC容器 - 需要2/3类型的帮助

Eri*_*ter 5 c# ioc-container inversion-of-control

背景

为了帮助提高我对IOC的理解以及如何使用它,我想创建一个所有三种IOC技术的示例:构造函数注入,Setter注入和接口注入,而不必使用第三方框架.我想我有一个构造函数注入的基本示例,但在使用setter和接口注入方面苦苦挣扎.

我的问题

您将如何从头开始处理写入界面和设置器注入?

这是我的想法,如果我走在正确的轨道上,请告诉我.

接口注入:

  1. 循环遍历使用构造函数注入实例化的已解析对象,检查以查看interfaceDependencyMap中实现的接口
  2. 定义某种interfaceDependencyMap以将接口与实现相关联.
  3. 使用interfaceDependencyMap解析实现
  4. 将适当的属性分配给使用构造函数注入初始化的对象

塞特犬注射:

  1. 循环使用构造函数注入实例化的已解析对象
  2. 定义某种setterInjectionMap
  3. 使用构造函数映射从MethodInfo解析预期参数
  4. 调用传入已解析参数对象的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));
    }
}
Run Code Online (Sandbox Code Playgroud)

def*_*mer 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
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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());
}
Run Code Online (Sandbox Code Playgroud)

如果您想获得更高级的知识,我建议您获取其中任何一个的源代码:SimpleInjectorAutofacNinjectStructureMap