本文介绍了JavaScript的DI / IoC的等价标准DI模式对静态类型语言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET和Java都有提供给他们DI / IoC容器中,摆每个
有一些模式,我发现在
与他们一起工作的不同点非常有用的。我现在是在一个地步,我想这样做相当于
的东西在JavaScript中。由于JavaScript是一种动态语言,我不希望
DI / IoC容器中,有直接对应到在静态类型语言中发现这样的替代品,这些
模式的容器的所有功能提供
受欢迎的。我也期待在
的JavaScript提供的DI / IoC容器中,将它们的功能有所不同,所以在不同
容器引用欢迎。

.NET and Java both have a slew of DI/IoC containers available to them and eachhave a number of patterns that I've found very useful at various points inworking with them. I'm now at a point where I would like to do equivalentthings in JavaScript. As JavaScript is a dynamic language, I don't expectDI/IoC containers to have direct equivalents to all the functionality providedby the containers found in statically typed languages so alternatives to thesepatterns are welcome. I also expect that the DI/IoC containers available inJavaScript will vary in their functionality, so references to varyingcontainers are more than welcome.

下面的图案是那些由的支持,我认为适用于动态语言
。有关这些模式
和关系的一般信息,请参阅

。大多数情况下,如果不是全部的
下面的概念也在其他语言和DI / IoC容器中,
如和。

The following patterns are those supported by Autofac 3 that I believe areapplicable to dynamic languages. For general information about these patternsand relationships, seehttp://autofac.readthedocs.org/en/latest/resolve/relationships.html andhttp://nblumhardt.com/2010/01/the-relationship-zoo/. Most, if not all, of theconcepts below are also available in other languages and DI/IoC containerssuch as Google Guice and Spring.

什么是?最近等同的概念和模式在JavaScript中描述如下

What are the nearest equivalents to the concepts and patterns described below in JavaScript?

在IoC容器可以创建一个类型的实例,它需要的类型的感知
。这是通过登记完成。注册通常是做
声明:

Before the IoC container can create instances of a type, it needs to be awareof the type. This is done through registration. Registration is usually donedeclaratively:

class A {}
var builder = new ContainerBuilder();
builder.RegisterType<A>();



以上,使IoC容器知道A型的它通过发现A的
的依赖反射。登记也可通过充当工厂
功能发生。这些功能通常是lambda表达式,可能是
写成内联:

The above makes the IoC container aware of the type A. It discovers A'sdependencies through reflection. Registration can also happen throughfunctions that act as factories. These functions are often lambdas and may bewritten inline:

class B {}
class A {
    A(string name, B b) { }
}
builder.RegisterType<B>();
builder.Register(c => // c is a reference to the created container
    new A("-name-", c.Resolve<B>()));



能够提供工厂的功能是非常有用的可以用一个依赖,这不是一个服务,
如在上面的例子中的名称参数

Being able to provide factory functions is especially useful when you have atype that needs to be parameterized with a dependency that's not a service,such as the name in the example above.

由于C#支持接口和抽象类,这经常不是
具体的数据类型是很重要的,而是抽象类型,它
器具。在这种情况下,你会注册类型的接口或
抽象类就可以将其下:

As C# supports interfaces and abstract classes, it's frequently not theconcrete data type that's important but instead the abstract type that itimplements. In these cases you'll register the type as the interface orabstract class under which it should be available:

interface IPlugin {}
class P : IPlugin
builder.RegisterType<P>().As<IPlugin>();

通过上面的注册,任何试图请求 P 会失败,但对于 IPlugin 将接替

With the above registration, any attempt to request a P would fail, but arequest for an IPlugin would succeed.

一旦所有的注册已经完成,容器需要创建

Once all of the registrations have been performed, the container needs to becreated:

public class Program {
    public static void Main(string[] args) {
        var builder = new ContainerBuilder();
        /* perform registrations on builder */
        var container = builder.Build();
        /* do something useful with container */
    }
}



有用

容器被创建在项目生命周期的早期,并成为
组成根源 - 这构成了应用程序的所有作品
代码中的位置,以确保所有必要的依赖被创建。
的容器,然后用于解析
应用程序中的主要成分:

The container is created very early in the program lifecycle and becomes thecomposition root -- the location within the code that composes all the piecesof the application, ensuring that all the necessary dependencies are created.The container is then used to resolve the main component within theapplication:

public static void Main(string[] args) {
    var builder = new ContainerBuilder();
    /* perform registrations on builder */
    var container = builder.Build();
    var application = container.Resolve<Application>();
    application.Launch();
}



概念3:终身&放大器;实例管理



假设:

Concept 3: Lifetime & instance management

Given:

class A {}

如果我们希望有一个为每个依赖创造了一个新的实例,它可以注册为<$
C $ C> builder.RegisterType< A>()而不需要进一步明确什么

If we want a new instance of A created for every dependency, it can beregistered as builder.RegisterType<A>() without need to specify anythingfurther.

如果我们想的一样。 A的实例被每一个需要我们
注册为SingleInstance的时间返回:

If we want the same instance of A to be returned every time we need toregister it as a 'SingleInstance':

builder.RegisterType<A>().SingleInstance();



有时候,我们希望在一定范围内,我们希望不同的范围内,但为
股的一个实例不同的实例。例如,我们可能想
股用于处理特定
HTTP请求所有的DAO在一个单一的数据库连接。这通常是通过为每个HTTP
请求一个新的范围,然后确保新范围用于解析
依赖性完成。在Autofac如下这可以手动控制:

Sometimes we want to share an instance within a certain scope but fordifferent scopes we want different instances. For example, we might want toshare a single database connection within all DAOs used to process a specificHTTP request. This is typically done by creating a new scope for each HTTPrequest and then ensuring that the new scope is used to resolve thedependencies. In Autofac this can be controlled manually as follows:

builder.RegisterType<A>().InstancePerLifetimeScope();
var scope = container.BeginLifetimeScope();
// within the request's scope
var root = scope.Resolve<RequestProcessor>();
root.Process();



常规模式



模式1:需要b的实例



General Patterns

Pattern 1: A needs an instance of B

class B {}     // registered as: builder.RegisterType<B>()
class A {      // registered as: builder.RegisterType<A>()
    A(B b) {}
}

var a = container.Resolve<A>();



IoC容器使用反射来发现B上的依赖,并注入
吧。

The IoC container uses reflection to discover the dependency on B and injectit.

class B {}
class A {
    A(Lazy<B> lazyB) {
        // when ready for an instance of B:
        try {
            var b = lazyB.Value;
        } catch (DependencyResolutionException) {
            // log: unable to create an instance of B
        }
    }
}

在此模式需要被推迟
因故依赖关系的实例。在这种情况下,让我们假设B是由一个第三
方创建的插件,其结构可能会失败。 。为了安全地使用它的
对象的构造将不得不谨慎

In this pattern the instantiation of the dependency needs to be delayed forsome reason. In this case, let's assume that B is a plugin created by a 3rdparty and whose construction may fail. In order to safely work with it theobject construction would have to be guarded.

class B {}
class A {
    A(Func<B> factory) {
        try {
            // frequently called multiple times
            var b = factory.Invoke();
        } catch (DependencyResolutionException) {
            // log: Unable to create
        }
    }
}

这模式通常用于有需要创建一个非价值对象的多个
实例。这也使
实例的创建要推迟,但通常出于不同的原因要比模式2的
这样做(A在未来的某一时刻需要一个B)。

This pattern is typically used when there's a need to create multipleinstances of a non value object. This also allows the creation of theinstance to be deferred but usually does so for different reasons than thosein Pattern 2 (A needs a B at some point in the future).

class X {}
class Y {}
class B {
    B(X x, Y y) { }
}

这模式通常用于注入的依赖需要被控制或配置
。举个例子,需要提供一个数据库
连接字符串DAO:

This pattern is typically used when an injected dependency needs to becontrolled or configured. Consider, for example, a DAO that needs a databaseconnection string provided:

class DAO {
    DAO(string connectionString) {}
}
class A {
    A(Func<DAO> daoFactory) {
        var dao = daoFactory.Invoke("DATA SOURCE=...");
        var datum = dao.Get<Data>();
    }
}



模式5:A需要的所有种类的B



Pattern 5: A needs all the kinds of B

interface IPlugin {}
class X: IPlugin {} // builder.RegisterType<X>().As<IPlugin>()
class Y: IPlugin {} // builder.RegisterType<Y>().As<IPlugin>()
class Z: IPlugin {} // builder.RegisterType<Z>().As<IPlugin>()
class A {
    A(IEnumerable<IPlugin> plugins) {
        foreach (var plugin in plugins) {
            // Add all plugins to menu
        }
    }
}

在这种格局多次登记对于给定的类型制成。那么消费者
可请求类型的所有实例,并相应地使用它们

In this pattern multiple registrations are made for a given type. The consumercan then request all instances of the type and use them accordingly.

class B {} // builder.RegisterType<B>().WithMetadata("IsActive", true);

// A needs to know about B
class A {
    A(Meta<B> metaB) {
        if ((bool)metaB.Metadata["IsActive"]) {
            // do something intelligent...
        }
    }
}

// OR...

class B {} // builder.RegisterType<C>().WithMetadata<X>(...);
class X {
    bool IsActive { get; }
}

// A needs to know X about B
class A {
    A(Meta<B, X> metaB) {
        if (metaB.IsActive) {
            // do something intelligent...
        }
    }
}

让我们再次说,我们有一个使用插件的系统。插件可以是
启用或禁用或在使用者的意愿重新排序。由元数据
相各插件的系统相关联可以忽略不活动的插件,或将插件中
按用户所希望的顺序

Let's again say that we have a system that uses plugins. The plugins may beenabled or disabled or reordered at the user's will. By associating metadatawith each plugin the system can ignore inactive plugins, or put the plugins inthe order desired by the user.

interface IPlugin:
class Plugin1 : IPlugin {}
class Plugin2 : IPlugin {}
class Plugin3 : IPlugin {}
class PluginUser {
    PluginUser(IEnumerable<Lazy<IPlugin>> lazyPlugins) {
        var plugins = lazyPlugins
                        .Where(CreatePlugin)
                        .Where(x => x != null);
        // do something with the plugins
    }

    IPlugin CreatePlugin(Lazy<IPlugin> lazyPlugin) {
        try {
            return lazyPlugin.Value;
        } catch (Exception ex) {
            // log: failed to create plugin
            return null;
        }
    }
}

在我们请求此代码示例包裹在一个慵懒的对象
,使他们能够创建或解决在将来的某个时刻的所有插件的列表。这种
允许他们的实例来加以防护或过滤

In this code sample we request a list of all plugins wrapped in a Lazy objectso that they can be created or resolved at some point in the future. Thisallows their instantiation to be guarded or filtered.

这例子

Another implementation worth looking at is of Angular JS DI:https://docs.angularjs.org/guide/di

您可以轻松地将模块(功能单位裹着一个封闭件和元数据)
以这样的方式来实现抽象出来。它允许切换执行,
运行测试单位嘲笑等等。

You can easily inject modules (units of functionality wrapped in a closure and metadata)in such a way that implementation is abstracted away. It allows to switch implementation,run mocks in test units and much more.

希望它能帮助

这篇关于JavaScript的DI / IoC的等价标准DI模式对静态类型语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 21:19
查看更多