Giter VIP home page Giter VIP logo

simpleinjector / simpleinjector Goto Github PK

View Code? Open in Web Editor NEW
1.2K 56.0 150.0 24.48 MB

An easy, flexible, and fast Dependency Injection library that promotes best practice to steer developers towards the pit of success.

Home Page: https://simpleinjector.org

License: MIT License

C# 99.18% Batchfile 0.81% Smalltalk 0.01% VBScript 0.01%
dependency-injection simpleinjector c-sharp ioc-container di-container

simpleinjector's Introduction

Simple Injector

NuGet

To get a high level overview of Simple Injector, please visit our website or dive directly into our documentation. And did you know there's a Simple Injector blog?

The goal of Simple Injector is to provide .NET application developers with an easy, flexible, and fast Dependency Injection library that promotes best practice to steer developers towards the pit of success.

Many of the existing DI libraries have a big complicated legacy API or are new, immature, and lack features often required by large scale development projects. Simple Injector fills this gap by supplying a simple implementation with a carefully selected, but complete set of features that allow you to write highly maintainable applications. Features like decorator registration and container-verification set it apart from the other containers. In the end, you will realize that there only two types of DI Containers—Simple Injector... and the rest.

The following platforms are supported:

  • .NET 4.5 and up.
  • .NET Standard including:
    • Universal Windows Programs.
    • Mono.
    • .NET Core, .NET 5 and up.
    • Xamarin.

Simple Injector is carefully designed to run in partial / medium trust, and it is fast; blazingly fast.

Getting started

The easiest way to get started is by installing the available NuGet packages. Take a look at the Using section in the documentation on learning how to configure and use Simple Injector. Go to the Integration page to find out how to integrate Simple Injector in your favorate application framework. Look at the More Information section to learn more or if you have any questions.

A Quick Example

Dependency Injection

The general idea behind Simple Injector (or any DI library for that matter) is that you design your application around loosely coupled components using the dependency injection pattern while adhering to the Dependency Inversion Principle. Take for instance the following UserController class in the context of an ASP.NET MVC application:

Note: Simple Injector works for many different technologies and not just MVC. Please see the integration for help using Simple Injector with your technology of choice.

public class UserController : Controller
{
    private readonly IUserRepository repository;
    private readonly ILogger logger;

    // Use constructor injection for the dependencies
    public UserController(IUserRepository repository, ILogger logger)
    {
        this.repository = repository;
        this.logger = logger;
    }

    // implement UserController methods here:
    public ActionResult Index()
    {
        this.logger.Log("Index called");
        return View(this.repository.GetAll());
    }
}
    
public class SqlUserRepository : IUserRepository
{
    private readonly ILogger logger;

    // Use constructor injection for the dependencies
    public SqlUserRepository(ILogger logger)
    {
        this.logger = logger;
    }
    
    public User GetById(Guid id)
    {
        this.logger.Log("Getting User " + id);
        // retrieve from db.
    }
}

The UserController class depends on the IUserRepository and ILogger interfaces. By not depending on concrete implementations, you can test UserController in isolation. But ease of testing is only one of a number of things that Dependency Injection gives you. It also enables you, for example, to design highly flexible systems that can be completely composed in one specific location (often the startup path) of the application.

Introducing Simple Injector

Using Simple Injector, the configuration of the application using the UserController and SqlUserRepository classes shown above, might look something like this:

protected void Application_Start(object sender, EventArgs e)
{
    // 1. Create a new Simple Injector container
    var container = new Container();

    // 2. Configure the container (register)
    container.Register<IUserRepository, SqlUserRepository>(Lifestyle.Transient);
    container.Register<ILogger, MailLogger>(Lifestyle.Singleton);   
    container.Register<UserController>();

    // 3. Optionally verify the container's configuration.
    container.Verify();

    // 4. Register the container as MVC3 IDependencyResolver.
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}

Tip: If you start with a MVC application, take a look at the ASP.NET MVC integration guide.

The given configuration registers implementations for the IUserRepository and ILogger interfaces. The code snippet shows a few interesting things. First of all, you can map concrete instances (such as SqlUserRepository) to an interface or base type. In the given example, every time you ask the container for an IUserRepository, it will always create a new SqlUserRepository on your behalf (in DI terminology: an object with a Transient lifestyle).

The seconds registration maps the ILogger interface to a MailLogger implementation. This MailLogger is registered with the Singleton lifestyle—only one instance of MailLogger will ever be created by the Container.

Using this configuration, when a UserController is requested, the following object graph is constructed:

new UserController(
    new SqlUserRepository(
        logger),
    logger);

Note that object graphs can become very deep. What you can see is that not only UserController contains dependencies, so does SqlUserRepository. In this case SqlUserRepository itself contains an ILogger dependency. Simple Injector will not only resolve the dependencies of UserController but will instead build a whole tree structure of any level deep for you.

And this is all it takes to start using Simple Injector. Design your classes around the SOLID principles and the Dependency Injection pattern (which is actually the hard part) and configure them during application initialization. Some frameworks (such as ASP.NET MVC) will do the rest for you, other frameworks (like ASP.NET Web Forms) will need a little bit more work. See the integration guide for examples of many common application frameworks.

Please go to the using section in the documentation to see more examples.

More information

For more information about Simple Injector please visit the following links:

Happy injecting!

simpleinjector's People

Contributors

abatishchev avatar borrrden avatar bouke avatar davidroth avatar dotnetjunkie avatar jawn avatar kwlin avatar lobster2012-user avatar qujck avatar seangwright avatar simpleinjector avatar theunrepentantgeek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simpleinjector's Issues

Expand existing RegisterAll dynamically

I am currently building a component that needs to use a collection of IThing, this is an abstract example of course. Using SimpleInjector it is possible to register multiple services using RegisterAll. This works of course great... unless you want to dynamically register more services, for example using SimpleInjector.Packaging.

Is there a built in way to do this using SimpleInjector? If not, how would I do this, and are there better ways? I noticed that it is sometimes possible to abuse the decorator pattern for this.

Allow resolved root objects to be intercepted

Intercepting the creation of root objects (objects that are resolved directly by calling container.GetInstance or InstanceProducer.GetInstance) enables some interesting features:

  • It allows diagnostic tools to hook onto the container and monitor what types are requested.
  • It allows users to run the creation of a root type within a certain scope, which allows the creation of a PerGraph scope.

Promosed syntax:

container.Options.RegisterResolveInterceptor(
    interceptor: (context, producer) =>
    {
        Console.WriteLine("Resolving: " + context.Producer.ServiceType.Name);
        return producer.Invoke();
    },
    predicate: context => true);

Variance not working for uncontrolled collection

Considering the following classes:

public class ClassA {}
public class ClassB : ClassA {}
public class ClassC : ClassA {}
public interface IIndexBuilder<out TObject> {}
public class IndexBuilderB : IIndexBuilder<ClassB> {}
public class IndexBuilderC : IIndexBuilder<ClassC> {}

The following doesn't work:

container.RegisterAll(typeof(IIndexBuilder<ClassB>), new[] { new IndexBuilderB() });
container.RegisterAll(typeof(IIndexBuilder<ClassC>), new[] { new IndexBuilderC() });
container.GetAllInstances<IIndexBuilder<ClassA>>(); // returns empty collection

And neither does this:

container.RegisterAll<IIndexBuilder<ClassB>>(new[] { new IndexBuilderB() });
container.RegisterAll<IIndexBuilder<ClassC>>(new[] { new IndexBuilderC() });
container.GetAllInstances<IIndexBuilder<ClassA>>(); // returns empty collection

But this does:

container.RegisterAll(typeof(IIndexBuilder<ClassB>, new[] { typeof(IndexBuilderB) });
container.RegisterAll(typeof(IIndexBuilder<ClassC>, new[] { typeof(IndexBuilderC) });
container.GetAllInstances<IIndexBuilder<ClassA>>(); // returns collection with 2 elements

As well as this:

container.AppendToCollection(typeof(IIndexBuilder<>),
    Lifestyle.Singleton.CreateRegistration<IndexBuilderB>(() => new IndexBuilderB(), container));
container.AppendToCollection(typeof(IIndexBuilder<>),
    Lifestyle.Singleton.CreateRegistration<IndexBuilderC>(() => new IndexBuilderC(), container));
container.GetAllInstances<IIndexBuilder<ClassA>>(); // returns collection with 2 elements

RegisterAll(Type, object[]) does not accept open-generic service types.

The RegisterAll overload that accepts a list of singletons is unable to work with open-generic service types and throws a confusing exception:

Since v2.7 Simple Injector allows the RegisterAll(Type, Type[]) method to accept open-generic service types. The RegisterAll(Type, Registration[]) method however, does not accept open-generic types, but throws the following exception:

The supplied type {0} is an open generic type. This type cannot be used for registration using this method. You can use one of the SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric extension method overloads for mapping an generic abstraction to an generic implementation, or use one of the SimpleInjector.Extensions.OpenGenericBatchRegistrationExtensions.RegisterManyForOpenGeneric extension method overloads for registering a set of implementations for a generic abstraction.

Allow creating InstanceProducers with specific dependent InstanceProducers

For instance:

var dep1 = Lifestyle.Transient.CreateProducer<IDep, Dep1>(container);
var dep2 = Lifestyle.Transient.CreateProducer<IDep, Dep2>(container);

// public Consumer(IDep dep) { }
var c1 = Lifestyle.Transient.CreateProducer<IConsumer, Consumer>(container, dep1);
var c2 = Lifestyle.Transient.CreateProducer<IConsumer, Consumer>(container, dep2);

Open questions:

How should the created producer handle the supplied dependencies?

  • Should it use the supplied dependencies to build up its direct dependencies?
  • Or should the dependencies be used recursively through the sub graph?
  • If so, how should be dealt with singleton registrations that are part of the graph and that depend on the supplied dependency?
  • Should the dependencies be applied solely to the concrete type, or should also any applied decorators be affected?

Add Lifestyle.Scoped lifestyle

The current way to make a scoped registration in Simple Injector is to create an instance of the particular lifestyle you need and to pass it on to one of the Register overloads, as follows:

var lifestyle = new ExecutionScopeLifestyle();
container.Register<IUserContext, AspNetUserContext>(lifestyle);

Most of the integration packages contain extension methods to make this process more convenient, such as:

container.RegisterPerWebRequest<IUserContext, AspNetUserContext>();
// or
container.RegisterWebApiRequest<IUserContext, AspNetUserContext>();

In most DI configurations however, you would see that there is only one particular type of scoped instance used, depending on the application type the code is running on, and most of the code does not care in which application the code runs, and therefore doesn't care about which scoped lifestyle is actually used. The registration just cares that the instance is 'scoped'.

To make this process easier, the following code should be made possible:

container.Register<IUserContext, AspNetUserContext>(Lifestyle.Scoped);

But since there are many types of 'scoped lifestyles', the container must be configured up front what for scoped lifestyle the user expects. We can use a constructor overload for this:

var container = new Container(new ExecutionContextScopeLifestyle());

Another option is to use the ContainerOptions for this:

var container = new Container();
container.Options.ScopedLifestyle = new ExecutionContextScopeLifestyle();

Combine IConstructorVerificationBehavior and IConstructorInjectionBehavior

In a quest to make interfaces narrow and follow the Interface Segregation Principle, Simple Injector 2.0 added three new interfaces that each contained one method. Later on however I realized that most (if not all) extendability scenarios that needed to implement one of those interfaces also needed the other one. Those two interfaces are IConstructorVerificationBehavior and IConstructorInjectionBehavior.

Since those interfaces are always used together, it is a very strong indication that they should have been one single interface in the first place and they should be merged together to one single interface.

Do note that this is a breaking change and means we need to bump the major version number when done. Happily just a handful of users actually use these extendability points, so the change can be done without breaking too many clients.

Allow creating InstanceProducers with specific dependent InstanceProducers

For instance:

var dep1 = Lifestyle.Transient.CreateProducer<IDep, Dep1>(container);
var dep2 = Lifestyle.Transient.CreateProducer<IDep, Dep2>(container);

// public Consumer(IDep dep) { }
var c1 = Lifestyle.Transient.CreateProducer<IConsumer, Consumer>(container, dep1);
var c2 = Lifestyle.Transient.CreateProducer<IConsumer, Consumer>(container, dep2);

Open questions:

How should the created producer handle the supplied dependencies?

  • Should it use the supplied dependencies to build up its direct dependencies?
  • Or should the dependencies be used recursively through the sub graph?
  • If so, how should be dealt with singleton registrations that are part of the graph and that depend on the supplied dependency?
  • Should the dependencies be applied solely to the concrete type, or should also any applied decorators be affected?

Allow Registration calls to be extended with fluent API

All RegisterXXX methods return void. If those methods instead would return some object that would describe the made registration(s), it would allow the library or its users to extend these objects with extension methods. This would result in more fluent APIs.

Note that changing the return type is a breaking change and this means that this can't be implemented in the v2.x branch.

Examples:

container.Register<ISomeService, MyService>()
    .OnActivation(service => service.TempDirectory = "c:\\temp")
    .DisposeOnEndOf(scopedLifestyle);

container.Register(typeof(ICommandHandler<>), applicationAssemblies)
    .WithPropertiesInjectedImplicitly()
    .WithConstructorOverloadResolution(new MostParametersConstructorResolutionBehavior());

container.Register(typeof(IRepository<>), typeof(Repository<>))
    .WithConstructorArgument("connectionString",  AppSettings["AppConString"]);

Move LifetimeScoping one namespace up the chain

The LifetimeScoping features of Simple Injector are located in the SimpleInjector.Extensions.LifetimeScoping namespace. Because of the removal of the SimpleInjector.Extensions namespace (see issue #7), it would make sense to move these features into the SimpleInjector.LifetimeScoping namespace, or perhaps even integrate this lifestyle into the core library.

New strategy (behavior) for influencing the types found using batch registration.

It is currently hard for the user to influence the batch-registration process. This is currently done by calling a static method one a class that is quite hidden. The list of types that is returned from that can be filtered and supplied to the RegisterAll method or a Register method. If you have multiple generic abstractions that need the same kind of filtering, you'll be duplicating that code.

Instead an extension point should be added to the container that allows the batch-registration facility to query that extension point to ask if a given implementation should be registered or not.

For instance:

public interface IBatchRegistrationBehavior
{
    bool ShouldRegisterType(Type serviceType, Type implementationType);
}

The default implementation can filter out decorators by default, and perhaps code contract classes, as described in this work item.

TornLifestyle warning caused by decorator registration

I have a class implementing multiple role-interfaces and would like to decorate one of those role interfaces.

public interface IA { }
public interface IB { }

public class ABComposite : IA, IB { }
public class BDecorator : IB 
{
    public BDecorator(IB b) { }
}

I register ABComposite like this:

 var container = new Container();

var registration = Lifestyle.Singleton.CreateRegistration<ABComposite>(container);
container.AddRegistration(typeof(IA), registration);
container.AddRegistration(typeof(IB), registration);

This registration passes the following unit test:

container.Verify();

var results = Analyzer.Analyze(container);
Assert.Empty(results);

Then I register the decorator like this:

container.RegisterSingleDecorator(typeof(IB), typeof(BDecorator));

Now the unit test fails because results have the following TornLifeStyle warnings:

IA: The registration for IA maps to the same implementation and lifestyle as the registration for IB does. They both map to ABComposite (Singleton). This will cause each registration to resolve to a different instance: each registration will have its own instance.
IB: The registration for IB maps to the same implementation and lifestyle as the registration for IA does. They both map to ABComposite (Singleton). This will cause each registration to resolve to a different instance: each registration will have its own instance.

It turns out that only one instance of ABComposite is created. This is the desired behavior, so I believe the container is working correctly, however the Analyzer is not.

Allow batch-registration to suppress contract classes

Using code contracts, developers can define contract classes for abstractions, as follows:

[ContractClass(typeof(ContractClassForIFoo))]
public interface IFoo {
    int DoThing(string x);
}

public class Foo : IFoo { ... }

[ContractClassFor(typeof(IFoo))]
public class ContractClassForIFoo : IFoo {
    public int DoThing(string x) {
        Contract.Requires<ArgumentNullException>(x != null);
        return 0;
    }
}

For Simple Injector this is currently fine, because:

  • Simple Injector currently only contains batch-registration features for generic types, and non-generic interfaces are not registered.
  • If a developer defines an open-generic contract class, the batch-registration facility will not pick it up, because it only selects non-generic implementations of generic interfaces.

This will change in the future, when we allow collections of non-generic abstractions to be registered using a RegisterAll/RegisterCollection overload that accepts a list of Assembly instances.

When we start doing that, it becomes interesting to suppress these contract classes -or- allow the user to change the container's default behavior to suppress the registration of these classes.

Replace SimpleInjector.Extensions namespace

For Simple Injector v3, the features in the extensions namespace should be replaced with features in the core library. For instance:

  • RegisterDecorator should become instance methods on the Container and extra RegisterDecorator<TService, TDecorator>() overloads should be added.
  • RegisterManyForOpenGeneric should be replaced with some batch registration facility. See the discussion here. This means splitting it into a method for registering collections and one for one-to-one mappings of open generic types.
  • RegisterOpenGeneric should be either become an instance method of Container, or should be integrated in Register (i.e. Register could allow working with open generic types).
  • RegisterAllOpenGeneric can be removed completely. This method is already redundant and RegisterAll enables the same functionality.

Lower memory pressure by reusing empty arrays

During the initialization phase, many empty arrays are created. Many of these created arrays are cached for the lifetime of the container, which increases the memory pressure of the application (a bit).

By reusing those empty arrays, we can reduce memory pressure. Reusing those arrays can be done by using System.Type.EmptyTypes instead of new Type[0] and our own internal structure that caches arrays. For instance:

internal static Array<T> {
    internal readonly static T[] Empty = new T[0];
}

Clean up old backward compatibility code

Other legacy stuff to fix:

  • Remove Container.InjectProperties.
  • Make WcfOperationScope internal.
  • Remove SimpleInjectorWcfExtensions.EnablePerWcfOperationLifestyle. It has been made obsolete in v2.8
  • Make LifetimeScope internal. There is no reason for clients to depend on an LifetimeScope directly, because it exposes no new members.
  • Remove SimpleInjectorLifetimeScopeExtensions.EnableLifetimeScoping. It has been marked obsolete since v2.5.2.
  • Remove SimpleInjectorWebExtensions.RegisterForDisposal.
  • Remove SimpleInjectorMvcExtensions.RegisterMvcAttributeFilterProvider.

Add more methods for conditional registrations to the core library

The core library currently contains methods for conditionally registering open generic types and decorators using RegisterOpenGeneric and RegisterDecorator. This feature should be extended to non-generic or closed-generic registrations as well.

The extension of this feature can partly replace RegisterWithContext method that is currently given as example in the documentation. Just like with is possible with the RegisterWithContext, the feature in the core library should allow the user to make a decision on its direct parent. Ideally this information should also be included for conditional open generic registrations and decorators.

In contrast with the RegisterWithContext extension method however, the built-in feature should not allow users to supply a factory delegate, but only allow supplying either an implementation type or a Registration instance. Allowing a user to supply a factory delegate would blind the diagnostic system and would make the registration transient and thereby force all parents up the chain to be transient as well (to prevent lifestyle mismatches / captive dependencies).

While RegisterWithContext allows the object graph to be built-up using runtime decisions, the new core feature should only allow to make decisions based on information known during the building of the object graph, just as is currently the case with both open generics and decorators. The predicate is called a finite number of times and the information burned in the compiled code that builds the object graph. This is important, because runtime information should never influence the structure of the object graph. The shape of the object graph should be fixed, and runtime information should instead be queried at runtime to change the application's call graph; not the object graph.

Although tempting, this new feature should not allow a registration to query information beyond its direct parent. Analyzing the parent's parent might seem useful, but will give incorrect results if direct parent is anything but transient (again causing the whole object graph to become transient).

While the RegisterWithContext only supports dependencies that are injected as constructor argument, the core feature should also support dependencies that are injected through property injection, since the core library supports property injection.

How to register an OpenGeneric in WebApi 2?

I have the following in my current MVC project:

private static void InitializeContainer(Container container)
{
            container.RegisterOpenGeneric(typeof(IUnitOfWork<>), typeof(UnitOfWork<>), 
            new WebRequestLifestyle());          
}

Now, we are moving to a project that uses WebAPI 2, in a similar architecture. How to register an open generic type like above? I think WebRequestLifestyle is not the correct way in this case...

I've tried and works:

container.RegisterOpenGeneric(typeof(IUnitOfWork<>), typeof(UnitOfWork<>), Lifestyle.Transient);

...but I have no idea if it´s correct or no.

UserContext is directly or indirectly depending on itself.

But its not ... that I can see!

UserContext registration:

container.Register<IUserContext, UserContext>(defaultAppLifeStyle);

Database Registration:

container.Register(() =>
{
    var logger = container.GetInstance<ILogger>();
    var userContext = container.GetInstance<IUserContext>();
    return new LENSSContext(nameOrConnectionString, logger, userContext);
}, defaultAppLifeStyle);

Fails on return new LENSSContext

The configuration is invalid. The type UserContext is directly or indirectly depending on itself.

Disallow wrapping container uncontrolled collections with singleton decorators

Because of backwards compatibility the container allows wrapping elements of container uncontrolled collections with decorators that are registered as singleton. This can however easily go wrong, when the enumerable is dynamic of nature.

This behavior should be disallowed and an exception should be thrown. This is a breaking change and should therefore be implemented in the next major release (v3).

Instead of disallowing this, it might be able to add a diagnostic warning instead. This can be implemented without introducing a breaking change and can be added in any minor release.

Registration of a service after resolution

Hi,

I understand that SimpleInjector's container is locked, and doesn't let you register services after the first resolution, by design. But there are many cases where one would like to resolve certain services during the startup-phase, in between registrations. I've also seen tid-bits of these discussions in many places, but unfortunately, I was unable to get a clean solution for the same so far. The documentation also seems to touch on this a bit, but just barely.

I was wondering if you could please give a quick scrip on what's the intended best way to accomplish this:

public BootstrapperClass1 {
  public void Register(Container c)
  {
      c.Register<IService1, Service1>();
  }
}

public BootstrapperClass2 {
  public void Register(Container c)
  {
     // This is just to substantiate the notion 
     // that the service has to be resolved here, and more registration
     // to proceed after that. 
     if (c.GetInstance<IService1>().Version == 1)
     {
           c.Register<IService2, Service2v1>();
      }
      else {
        c.Register<IService2, Service2v2>();
      }
  }
}

One obvious way that I see is to use the UnresolvedType event. But the obvious problem is that, this ends up complicating the whole registration logic for anything beyond that. And you have to end up doing almost the entire rest of the registration logic as a part of that event, which seems highly unnatural.

A whole bunch of my projects use multi-stage bootstrappers like these, where a later bootstrapper will need to examine registered services so far before they make their registrations and this seems make it quite difficult to migrate to SI.

The only way I seem to be able to workaround this is by creating a whole bunch of different containers, and composing the registrations of the containers to a new one. This is bugging me since it isn't the cleanest approach, and also becomes very expensive on the startup path, as the startup stages increase.

What is the correct way to resolve a per-request service in a property-injection initializer block?

I am using property injection in a few places in an ASP.NET MVC application where I am retrofitting SimpleInjector to replace Ninject. My question is: If I have properties that want to be injected with values that are have a "per-request" lifestyle, what is the best way to resolve them? Currently, my code looks like this:

container.RegisterInitializer<CerberusAuthorizeAttribute>(c =>
            {              
                c.AuthorizationModule = DependencyResolver.Current.GetService<ICerberusAuthorizationModule>();
                c.Order = 1;
            });

I'm using MVC's dependency resolver here, because it is aware of the current request scope, whereas I don't think(?) that the container would be. Is there another way to do this, that doesn't involve the MVC plumbing?

Thanks!

Remove public Container(ContainerOptions) overload

The overload constructor Container(ContainerOptions options) is a rarely used feature that has been superseeded by the Container.Options property. This constructor overload only adds complexity to the library and allows users two do things in multiple ways where there is no benefit in doing this.

Xamarin.Forms.Android Release Mode Binding Warnings

Howdy,

I'm getting the following warning when I build. This just started happening out of no where. Not sure what would have triggered it.

Found conflicts between different versions of the same dependent assembly. In Visual Studio, double-click this warning (or select it and press Enter) to fix the conflicts; otherwise, add the following binding redirects to the "runtime" node in the application configuration file:
simpleinjectorassemblybindings

It wouldn't let me copy XML in here and there doesn't seem to be a way to denote code. Makes perfect sense for a source code issue tracking system...

This is a Xamarin.Forms project. Any ideas?

Create InstanceProducer<TService>

Currently the InstanceProducer class is non-generic. This means that it's GetInstance method returns object. This causes users to have to apply casting themselves if they use the InstanceProducer class as follows:

var prod = Lifestyle.Scoped.CreateProducer<DbContext>(() => new DbContext("constr"), container);

container.RegisterSingle<IUnitOfWork>(
    new DbContextUnitOfWork(() => (DbContext)prod.GetInstance()));

If the Lifestyle.CreateProducer<T> methods would return an InstanceProducer<T> instead, this would make scenarios like these much cleaner, because that would allow the user to minimize the code to the following:

var prod = Lifestyle.Scoped.CreateProducer<DbContext>(() => new DbContext("constr"), container);

container.RegisterSingle<IUnitOfWork>(new DbContextUnitOfWork(prod.GetInstance));

Incorrect behavior with overlapping registration of collections

Simple Injector contains several ways to register collections. The most common way is to call RegisterAll while supplying types, but other options are:

  • Calling RegisterAll while supplying a list of instances (singletons).
  • Calling RegisterAll while supplying an enumerable (container uncontrolled collection).
  • Calling RegisterSingle<IEnumerable<...>> while supplying an enumerable.
  • Calling Register<IEnumerable<...>>(() => ...) while supplying a delegate that returns an enumerable.

When (accidentally) mixing these calls, Simple Injector not always detects these duplicate registrations and sometimes allows these registrations to take place. Effect is sometimes that the original registration is completely replaced, while other times the registration is completely ignored. This violates the design principles and should be fixed.

This problem was partly fixed for v2.8 and is described by similar work item 21004. However, only part of the problem was fixed in v2.8, because a thorough rewrite of the RegisterAll implementation is needed to pull this off. The remainder of this fix is therefore assign to a 3.x release.

The following tests demonstrate the problem:

[TestMethod]
public void RegisterAllOpenGeneric_CalledAfterRegisterForSameCollection_ThrowsMixingCallsNotAllowedException()
{
    // Arrange
    var container = new Container();

    container.Register<IEnumerable<IEventHandler<AuditableEvent>>>(() => null);

    // Act
    Action action = () => container.RegisterAll(typeof(IEventHandler<>), new[] 
    {
        typeof(AuditableEventEventHandler<>) 
    });

    // Assert
    AssertThat.ThrowsWithExceptionMessageContains<InvalidOperationException>(
        "Mixing calls to RegisterAll for the same open-generic service type is not supported.",
        action);
}

[TestMethod]
public void RegisterAllClosed_CalledAfterRegisterAllSingletonWithAllowOverridingRegistrations_CompletelyReplacesPrevious()
{
    // Arrange
    Type[] expectedHandlerTypes = new[] { typeof(AuditableEventEventHandler) };

    var container = new Container();

    container.Options.AllowOverridingRegistrations = true;

    container.RegisterAll<IEventHandler<AuditableEvent>>(new AuditableEventEventHandler<AuditableEvent>());

    // Act
    // Should Completely override the previous registration
    container.RegisterAll<IEventHandler<AuditableEvent>>(expectedHandlerTypes);

    // Assert
    var handlers = container.GetAllInstances<IEventHandler<AuditableEvent>>();

    Type[] actualHandlerTypes = handlers.Select(handler => handler.GetType()).ToArray();

    Assert.IsTrue(expectedHandlerTypes.SequenceEqual(actualHandlerTypes),
        "The original registration was expected to be replaced completely. Actual: " +
        actualHandlerTypes.ToFriendlyNamesText());
}

Allow collection registrations to be resolved using GetCurrentRegistrations(), even without a call to Verify()

This unit test fails:

container.RegisterCollection<ILogger>(new[] { typeof(FileLogger), typeof(MailLogger) });
var r1 = container.GetCurrentRegistrations();
container.Verify();
var r2 = container.GetCurrentRegistrations();
Assert.AreEqual(r1.Length, r2.Length);

The registrations for FileLogger and MailLogger are only known after the collection of loggers is resolved. This makes GetCurrentRegistrations undeterministic for the user, and can makes some scenarios harder for the user.

Challenge here is to make this change, without introducing a breaking change. How do we know when we introduced a breaking change? That's easy: the unit tests will fail :-)

RegisterAll(Type, Registration[]) does not accept open-generic types.

Since v2.7 Simple Injector allows the RegisterAll(Type, Type[]) method to accept open-generic service types. The RegisterAll(Type, Registration[]) method however, does not accept open-generic types, but throws the following exception:

The supplied type {0} is an open generic type. This type cannot be used for registration using this method. You can use one of the SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric extension method overloads for mapping an generic abstraction to an generic implementation, or use one of the SimpleInjector.Extensions.OpenGenericBatchRegistrationExtensions.RegisterManyForOpenGeneric extension method overloads for registering a set of implementations for a generic abstraction.

Let the container throw an exception when resolving an object graph that contains a lifestyle mismatch / captive dependency

Lifestyle mismatches (a.k.a. Captive Dependency) are one of the most serious misconfigurations a user can make, because it will almost always lead to bugs in production, while the application seems working while debugging. Because of this, we already decided to let the Verify method throw on diagnostic warnings by default in v3.

Not all users do call Verify however, and this makes it still very easy for such bug to stay unnoticed for a long period of time. Because of this I would like to take this even one step further and let the container throw an exception in case an object graph is resolved that contains such a lifestyle mismatch. This fits into Simple Injector's design strategy of failing fast.

The Lifestyle Mismatch is reasonably the only diagnostic warning that allows doing this, because the other warnings are either not severe enough to always throw an exception while resolving, or their verification spans multiple object graphs, forcing them to do a full analysis of the whole configuration (which might take a considerable amount of time).

Obviously, since we will be throwing an exception in a case where previously an object graph is returned, this is a breaking change.

Of course we also need a configuration switch (preferably in Container.Options) that disables this so users can fall back on the original behavior.

Drop support for Common Service Locator adapter

We are dropping support for the Common Service Locator adapter for Simple Injector v3. The Common Service Locator project is a painful failure from a design perspectice and the pattern behind it is an anti-pattern and even for reusable libraries and frameworks there are better methods available.

If users feel the need to use a framework or library that requires the CSL, the writing of an adapter is trivial as the following example shows:

using System;
using System.Collections.Generic;
using Microsoft.Practices.ServiceLocation;
using SimpleInjector;

public class SimpleInjectorServiceLocatorAdapter : IServiceLocator {
    private readonly Container container;
    public SimpleInjectorServiceLocatorAdapter(Container container) {
        this.container = container;
    }

    public IEnumerable<TService> GetAllInstances<TService>() {
        return this.container.GetAllInstances(typeof(TService)).Cast<TService>();
    }

    public IEnumerable<object> GetAllInstances(Type serviceType) {
        IServiceProvider serviceProvider = this.container;
        Type collectionType = typeof(IEnumerable<>).MakeGenericType(serviceType);
        var collection = (IEnumerable<object>)serviceProvider.GetService(collectionType);
        return collection ?? Enumerable.Empty<object>();
    }

    public TService GetInstance<TService>(string key) {
        return (TService)this.GetInstance(typeof(TService));
    }

    public TService GetInstance<TService>() {
        return (TService)this.container.GetInstance(typeof(TService));
    }

    public object GetInstance(Type serviceType, string key) {
        return this.GetInstance(serviceType);
    }

    public object GetInstance(Type serviceType) {
        return this.container.GetInstance(serviceType);
    }

    public object GetService(Type serviceType) {
        IServiceProvider serviceProvider = this.container;
        return serviceProvider.GetService(serviceType);
    }
}

Force Aggressive Inlining for .NET 4.5

.NET 4.5 allows aggressive inlining of methods by marking methods with [MethodImpl(MethodImplOptions.AggressiveInlining)]. We should add this attribute to places where this makes sense, to ensure those methods are inlined. Inlining is currently 'forced' by making the methods small enough and letting it not throw exceptions directly. This is a fragile and limited approach. So it makes sense to at least mark those methods with this attribute, and perhaps we can find other spots as well where this makes sense.

At least the following methods can be marked:

  • CyclicDependencyValidatorExtensions.CheckForRecursiveCalls
  • InstanceProducer.RemoveValidator
  • Requires.IsNotNull

Since this is .NET 4.5 only (not 4.0, no PCL), we need the following code:

#if NET45 
[MethodImpl(MethodImplOptions.AggressiveInlining)] 
#endif

Question: How to specify a Lifestyle with RegisterAll<>

I have SimpleInjector set as my DependencyResolver after the following configuration code:

var afterRequestTasks = assembly.GetTypes()
    .Where(t => typeof(IRunAfterEachRequest).IsAssignableFrom(t) && !t.IsInterface)
    .ToList();

container.RegisterAll<IRunAfterEachRequest>(afterRequestTasks);

and then in my global.asax.cs I have this:

protected void Application_EndRequest()
{
    try
    {
        foreach (var task in DependencyResolver.Current.GetServices<IRunAfterEachRequest>())
        {
            task.Execute();
        }
    }
    finally { }
}

Running this produces the following error:
"Cannot access a disposed object. Object name: SimpleInjector.Scope"

How can I modify the Lifetime of these types registered with RegisterAll so that I can access them in Application_EndRequest?

Stack trace:

[ObjectDisposedException: Cannot access a disposed object.
Object name: 'SimpleInjector.Scope'.]
   SimpleInjector.Scope.ThrowObjectDisposedException() +90
   SimpleInjector.Scope.RequiresInstanceNotDisposed() +38
   SimpleInjector.Scope.GetInstance(ScopedRegistration`2 registration) +58
   SimpleInjector.Scope.GetInstance(ScopedRegistration`2 registration, Scope scope) +207
   SimpleInjector.Advanced.Internal.LazyScopedRegistration`2.GetInstance(Scope scope) +242
   lambda_method(Closure ) +406
   SimpleInjector.InstanceProducer.GetInstance() +117

[ActivationException: The registered delegate for type IRunAfterEachRequest threw an exception. Cannot access a disposed object.
Object name: 'SimpleInjector.Scope'.]
   SimpleInjector.InstanceProducer.GetInstance() +222
   SimpleInjector.Advanced.<GetEnumerator>d__9.MoveNext() +228
   CustomAppFramework.Web.MvcApplication.Application_EndRequest() in c:\Development\Learning\CustomAppFramework\CustomAppFramework.Web\Global.asax.cs:47

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +192
   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +155
   System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +19
   System.Web.Util.ArglessEventHandlerProxy.Callback(Object sender, EventArgs e) +56
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

Add RegisterAll overload for batch registration

The current way of batch-registering collections in Simple Injector is using RegisterManyForOpenGeneric as follows:

container.RegisterManyForOpenGeneric(typeof(ISubscriber<>), container.RegisterAll,
    AppDomain.CurrentDomain.GetAssemblies());

We can simplify this by adding an overload of RegisterCollection (previously RegisterAll) that allows doing this:

container.RegisterCollection(typeof(ISubscriber<>), AppDomain.CurrentDomain.GetAssemblies());

// and
container.RegisterCollection(typeof(ISubscriber<>),
    AccessibilityOption.PublicTypesOnly,  
    AppDomain.CurrentDomain.GetAssemblies());

Original discussion: https://simpleinjector.codeplex.com/workitem/21005

And for one-to-one mappings, a Register overload can be added:

container.Register(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());

Avoid instances creation if HTTP Request is OPTIONS

Hi everyone! I would like to know if there's a workaround to avoid the unnecesary instance of the registered services if the Http request verb is OPTIONS.
I'm using WebApi with CORS enabled, and the default behavior of Chrome is to send first an http request with verb options to know the list of allowed methods before sending the original request.

As a result my services are instanced twice!

I post here because I see other people asking, so I hope not disturbing someone.

Cheers!

AccountController set up guide

Hello,

I am quite new about IoC and simpleInjector.

I am following the document and I just installed SimpleInjector.Integration.WebApi.WebHost.QuickStart package.(vs2013, asp.net mvc5, web api.2.2, individual identification)

I cannot get over the AccountController injection.

Could I get a step by step guide to set up AccountController using SimpleInjector?
I google it heaps but really hard to find a guide.

Sincerely,

How to use Simple Injector in ASP.NET vNext

I'm trying to hook up Simple Injector in a ASP.NET vNext project. Since, Simple Injector already implements IServiceProvider, I tried registering it like this:

public static class SimpleInjectorInitializer
{
  public static IServiceProvider Initialize(IConfiguration config, IServiceCollection services) {
    var container = new Container();
    container.RegisterCollection(services);

    // register app services

    container.Verify();

    return container;
  }
}

Startup.cs

public IServiceProvider ConfigureServices(IServiceCollection services) {
    // Add Application settings to the services container.
    services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));

    services.AddMvc();

    return SimpleInjectorInitializer.Initialize(Configuration, services);            
}

However, running the app gives me this error:

No service for type 'Microsoft.AspNet.Hosting.Builder.IApplicationBuilderFactory' has been registered.

Not using Simple Injector causes the app to run just fine (although it fails to inject anything but at least it doesn't throw this error).

Not sure what I'm missing.

Problem with scoping in Web API after updating from 2.7.3 to 2.8.0

Hi,
I tried to use the new 2.8.0 version and noticed that all my OWIN httplistener tests fail now with the following exception:

An error has occurred.","ExceptionMessage":"Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance."

I uploaded my test project to http://s000.tinyupload.com/index.php?file_id=51564532068892027082
This test project is a heavily reduced version of an evaluation project, if I can replace autofac by simple injector.

Setup:

  1. One Engine class, doing the container registration and setup
  2. Services and Controllers registered in that class
  3. A hybrid lifestyle of ExecutionContext and WebApiRequest
  4. I basically want to use the same "Engine" for both command line applications and for the Web project

In my test class I basically test two things, first that the Standalone resolving works (for the command line application) and if I can talk to an owin httplistener resolving all the controllers. (see the NUnit tests in the test project).

In 2.7.3 I could start my executionscope in the Engine and it worked for standalone, owin tests and IIS
In 2.8.0, if I start my executionscope in the Engine it only works for standalone and IIS, but not for the owin tests anymore.

I saw that you changed the webapi scope generation to be dependent on a previously existing scope, i.e. create the webapi scope only if no other scope exists (work item 21015). This works fine for IIS apparently, but for the Owin Httplistener apparently the executioncontext is still the same, so it never starts a new scope for each request resulting in the above error message. If i understand the scope stuff correctly, I basically had a nested scope previously (executioncontext first then the forced webapi request context), which is basically the same as I did in Autofac

I'm perfectly aware that I could pass the owin test server some setting to not start the executioncontext only for the owin part, but i would prefer not to, since currently I only have two execution paths for testing (standalone and web) and with that setting I have three paths (standalone, owin test and IIS).

I also know that I could easily write my own dependencyresolver which uses the old way, but i would prefer to use yours.

That's why I'm asking myself, is this a regression, is my Idea to have one Engine for both types of application completely nuts or did I miss something?

Regards,
Torni.

RegisterUnresolvedType event exception - explicit registration works

I am trying to use the RegisterUnresolvedType event, but I am getting an exception when calling container.Verify().

If i register my messagehandlers explicitly, it works fine. The following code demonstrates the problem:

public interface IMessageHandler<TMessage> { }
public class Message1 { }
public class Message2 { }
public class Service1 { public Service1(IMessageHandler<Message1> message1) { } }
public class Service2 { public Service2(IMessageHandler<Message2> message2) { } }
public class MessageHandlerBase<TMessage> : IMessageHandler<TMessage> { }

private static void Main(string[] args)
{
    Container container = new Container();

    container.RegisterSingle<Service1>();
    container.RegisterSingle<Service2>();

    container.ResolveUnregisteredType += (sender, e) =>
    {
        if (e.UnregisteredServiceType.IsGenericType &&
            e.UnregisteredServiceType.GetGenericTypeDefinition() == typeof(IMessageHandler<>))
        {
            var messageHandlerType = typeof(MessageHandlerBase<>).MakeGenericType(
                e.UnregisteredServiceType.GetGenericArguments());

            object messageHandler = container.GetInstance(messageHandlerType);

            // Register the instance as singleton.
            e.Register(() => messageHandler);
        }
    };

    container.Verify();
    DiagnosticResult[] results = Analyzer.Analyze(container);
}

The Analyzer.Analyze method throws a NullReferenceException with the following stack trace:

at SimpleInjector.Helpers.ToFriendlyName(Type type, Func`2 argumentsFormatter)
at SimpleInjector.Helpers.ToFriendlyName(Type type)
at SimpleInjector.Diagnostics.Analyzers.TornLifestyleContainerAnalyzer.BuildDescription(InstanceProducer diagnosedProducer, InstanceProducer[] affectedProducers)
at SimpleInjector.Diagnostics.Analyzers.TornLifestyleContainerAnalyzer.CreateDiagnosticResult(InstanceProducer diagnosedProducer, InstanceProducer[] affectedProducers)
at SimpleInjector.Diagnostics.Analyzers.TornLifestyleContainerAnalyzer.<Analyze>b__4(<>f__AnonymousType20`2 <>h__TransparentIdentifier0)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at SimpleInjector.Diagnostics.Analyzers.TornLifestyleContainerAnalyzer.Analyze(IEnumerable`1 producers)
at SimpleInjector.Diagnostics.Analyzer.<>c__DisplayClassb.<Analyze>b__2(IContainerAnalyzer analyzer)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at SimpleInjector.Diagnostics.Analyzer.Analyze(Container container)
at ConsoleApplication1.Program.Main(String[] args)

I am not sure what i am doing wrong?

Rename RegisterSingle methods to RegisterSingleton.

We like to minimize the API and improve confusing parts. The Container.RegisterSingle methods are confusing, because developers sometimes think those methods are the oposite of RegisterMany, while their behavior is completely unrelated.

We would have liked removing those methods altogether in favor of simply using Register overloads that take in a Lifestyle.Singleton, as in Register<HomeController>(Lifestyle.Singleton). We tried this model in the v3 alpha1 release, but this proved to be problematic for users, because it made moving from v2 to v3 extremely hard.

So instead, we rename the RegisterSingle methods to RegisterSingleton. This makes migrating much easier and at the same time makes the API much clearer, because RegisterSingle is still confusing while having RegisterCollection methods at the same time.

Add Register(Type, Assembly[]) overload for batch-registration of open-generic types

In Simple Injector 2.x the provided way to do batch-registration of open-generic types is using RegisterManyForOpenGeneric. The method name however is confusing, and it being part of the SimpleInjector.Extensions namespace makes this harder than required.

A new set of Register overloads that take in a list of assemblies can solve this:

container.Register(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());

Threading issue with .verify() method

Hi, just a small bug to report. I have the following 2 integration tests

[Fact]
public void Should_Verify_Api_Container()
{
    // some setup stuff
    container.Verify();
    var results = Analyzer.Analyze(container);
    // assert results are zero
}

[Fact]
public void Should_Verify_Worker_Container()
{
    // some setup stuff
    container.Verify();
    var results = Analyzer.Analyze(container);
    // assert results are zero
}

These test ran fine however when I upgraded to xunit 2.0 the tests started intermittently failing. By default in xunit 2 the tests all run in parallel. I added on the attribute [Collection("verify")] to each class containing the tests - which makes them run in sequence. This made the tests pass again. I can only assume there's a threading issue or something like that and thought you'd like to know.

Cheers
Neil

Confusing exception in case batch-registration skipped decorator

The following code:

public interface IService<T> { }
public class ServiceA : IService<A> {
    public ServiceA(IValidator<A> validator) { }
}
public class ServiceB : IService<B> {
    public ServiceB(IValidator<B> validator) { }
}
public class ServiceC : IService<C> {
    public ServiceC(IService<C> validator) { } // note the cyclic dependeny here.
}
public class CController {
    public CController(IService<C> service) { }
}

container.Register(typeof(IService<>), typeof(IService<>).Assembly);

container.GetInstance<CController>();

Results in the following exception:

The registered delegate for type CController threw an exception. The constructor of type CController contains the parameter of type IService<C> with name 'service' that is not registered. Please ensure IService<C> is registered, or change the constructor of CController.

This exception is expected because Register searches for all non-generic IService<T> implementations, but skips any decorators that it encounters. ServiceC is a decorator, because it implements IService<C> and (probably) accidentally depends on IService<C> as well. This means that ServiceC is not registered and there is therefore no registration for IService<C> and this will therefore cause the "Please ensure IService is registered" message.

Although this behavior is correct and by design, it can be really confusing for the user that didn't notice his mistype in the constructor. A better exception in this case therefore might be:

The constructor of type CController contains the parameter of type IService<C> with name 'service' that is not registered. Please ensure IService<C> is registered, or change the constructor of CController. Note that ServiceC was found as implementation of IService<C>, but it was skipped by the container because it contains a cyclic reference to itself.

Warn when a registered open generic has not been verified

tl;dr: the container cannot guess how to close an open generic type for verification.

The diagnostic services cannot verify an open generic that is not explicitly defined somewhere else within the source code as a closed type within a constructor (or as a property).

Can we have an info or warning message when a registered open generic has not been verified.

This should be an 'info' message.

Clean up old 2.4 backward compatibility code

There is some legacy design that was introduced in v2.4. In v3 we can make breaking changes and fix this old stuff:

  • Make ScopedLifestyle.WhenScopeEnds non-virtual.
  • Make ScopedLifestyle.RegisterForDisposal non-virtual.
  • Make ScopedLifestyle.CreateCurrentScopeProvider abstract.
  • Remove ScopedLifestyle.DisposeInstances.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.