StrangeIoC(一)

2019-01-29  本文已影响0人  虫小白

框架介绍

StrangeIoC是采用控制反转(IoC)思想书写的一个框架。

什么是控制反转呢?简单来说就是我们需要引用某一个类的实例时,不需要主动的获取(比如new一个实例然后对该实例引用,或者public之后在Unity的Inspector面板中拖拽),框架会自动把所需的实例传递给我们,StrangeIOC正是一个这样的框架。

在实际的项目中一个类可能会有多个实例,那么StrangeIOC如何知道我们想要的是哪一个实例呢?答案是通过“绑定”

现在看一个简单的例子:现在有类A、类B继承自Letter类,我们需要在客户端类Client中引用一个A的实例。

public class Letter
{
    public virtual void SayHi()
    {
        print("I am Letter")
    }
}

public class A:Letter
{
    public override void SayHi()
    {
        print("I am A")
    }
}

public class B:Letter
{
    public override void SayHi()
    {
        print("I am B")
    }
}

//不使用依赖注入
public class Client
{
    public Letter letter;

    public void Excute()
    {
        letter=new A();
        letter.SayHi();
    }
}

//使用依赖注入
public class Client
{
    [Inject]
    public Letter letter;

    public void Excute()
    {
        letter.SayHi();
    }
}

使用依赖注入时,如何将Client类中的letter和A类做一个绑定呢?我们只要在“某个特定的类”中写这样一句话:

Bind<Letter>().To<A>()

这样,我们需要Letter类的实例时,框架就会自动提供一个A的实例。(可能有读者想:我可能在某个地方引用Letter时想要一个B的实例呢,不要着急,以上代码不能真正运行,只是用来诠释原理,如何引用B会在后面讲到)

上面的“[Inject]”关键字是告诉程序,我这个地方的字段需要框架把具体实例放到这里。“某个特定的类”是指框架中的上下文类(上下文类可以理解为为程序正常运行提供一个环境的类,比如程序运行需要某些条件,上下文类可以创建这些条件)。

StrangeIOC的绑定类似一种键值对的形式,前面的键是输入,后面的值是输出。StrangeIOC为我们提供了以下几种绑定方式:

//泛型形式
Bind<Spaceship>().To<Liberator>();
//或者
Bind(typeof(Spaceship)).To(typeof(Liberator));

//值形式
Bind(“MeaningOfLife”).To(42);

//混合形式
Bind<Spaceship>().To(“Enterprise”);

现在基本上介绍完了。。。是不是毫无框架的感觉。。。上面的内容可以说是StrangeIOC框架的核心,好在框架作者在核心的基础上为我们扩展了一个MVCS版本的StrangeIOC框架。

[Inject]和上下文

在MVCS版本中,“[Inject]”只能用于属性和索引器,所以上面的客户端的写法应该是:

public class Client
{
    [Inject]
    public Letter letter{get;set;};

    public void Excute()
    {
        letter.SayHi();
    }
}

上下文在该版本中对应于的MVCSContext类;

绑定

在该版本中,作者为我们扩展了三种绑定:injectionBindermediationBindercommandBinder

//方式一,绑定到A的单例
injectionBinder.Bind<Letter>().To<A>().ToSingleton();

//方式二,绑定到A的某个特定实例
A instanceA=GameObject.Find("A").GetComponent<A>();//获取A的特定实例
injectionBinder.Bind<Letter>().ToValue(instanceA);

//方式三,创建一个A的实例并绑定
injectionBinder.Bind<Letter>().To<A>();

我们也可以为绑定添加名称用以区分不同的绑定,比如上面绑定Letter的例子可以改为:

injectionBinder.Bind<Letter>().To<A>().ToSingleton().ToName("NameA");
injectionBinder.Bind<Letter>().To<B>().ToName("NameB");

这样,我们在使用时通过给定不同的名称用以区分不同的实例:

//在客户端中
public class Client
{
    [Inject("NameA")]
    public Letter letterA{get;set;}

    [Inject("NameB")]
    public Letter letterA{get;set;}

    public void ExcuteA()
    {
        letterA.SayHi();
    }

    public void ExcuteB()
    {
        letterB.SayHi();
    }
}

也可以一次绑定多个:

injectionBinder.Bind<Letter>().Bind<Word>().To<A>().ToSingleton().ToName("NameA");

这样,我们在某个地方引用Letter或者Word时都会得到A的单例。

在上面的三种方式中,除了方式二,我们需要的实例都是StrangeIOC框架自动创建的,当存在多个构造函数时,框架优先使用使用“[Construct]”修饰的构造函数,如果不存在,则默认使用参数最少的构造函数。

public class A:Letter
{
    public A()
    {
        //默认使用这个构造函数
    }

    [Construct]
    public A(string arg)
    {
        //但是使用[Construct]标签的话,Strange会使用这个构造函数
    }
}

如果使用属性注入的话,[PostConstruct]将会是一个非常有用的标签. 任何使用[PostConstruct]标签的方法在属性注入后会被立即调用. 通过这种方式可以在属性注入完成后使用属性, 这是一个安全类型不会返回空指针.

[PostConstruct] 
public void PostConstruct() 
{ 
    //在这里处理一些一般在构造函数里面处理的事 
}

多个使用[PostConstruct]的方法可以按下面的方式按序执行

[PostConstruct(1)] 
public void PostConstructOne() 
{ 
    //第一个执行 
}

[PostConstruct(2)] 
public void PostConstructTwo() 
{ 
    //第二个执行 
}
上一篇下一篇

猜你喜欢

热点阅读