simpleinjector / documentation Goto Github PK
View Code? Open in Web Editor NEWDocumentation for Simple Injector in reStructureText
Documentation for Simple Injector in reStructureText
I think you're being a bit too extreme by recommending not using IOptions. The whole point of the abstraction is to allow runtime-reloading of your configs if they change.
If your component takes a dependency on the actual config object you can't change the config at runtime (like kubernetes configs for example)
It's not that hard to test either, there's a Options.Create
In your ASP.NET Core MVC Integration Guide the InitializeContainer
made in Configure
method.
Is this the right practice?
According to asp net documentation, Configure
is used to configure the request handling, and ConfigureServices
is used to registering services.
Simple Injector does not support looking at the Consumer's Consumer when doing context-based injection. The docs however dont explain why this limitation exists and how to work around this.
First of all sorry for so much code but i belive it will be easier to find an issue here. I am using SimpleInjector and getting error inside Program class on container.Verify(); line, it says as below. I was trying to investigate throug docs website but still cannot figoure out how to fix that.
SimpleInjector.DiagnosticVerificationException: 'The configuration is invalid. The following diagnostic warnings were reported: -[Disposable Transient Component] FrmLogin is registered as transient, but implements IDisposable. See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.'
Full code:
static class Program
{
private static Container container;
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(container.GetInstance<FrmLogin>());
}
private static void Bootstrap()
{
container = new Container();
container.Register<IRepositoryDal<User>, UserRepositoryDal>();
container.Register<IRepositoryDal<Order>, OrderRepositoryDal>();
container.Register<IDbManager>(() => new DbManager("sqlserver"));
container.Register<IGenericBal<User>, UserBal>();
container.Register<IGenericBal<Order>, OrderBal>();
container.Register<FrmLogin>();
container.Verify();
}
}
public partial class FrmLogin : Form
{
private readonly IGenericBal<User> _userBal;
private readonly IGenericBal<Order> _orderBal;
public FrmLogin(IGenericBal<User> userBal, IGenericBal<Order> orderBal)
{
InitializeComponent();
_userBal = userBal;
_orderBal = orderBal;
}
}
public interface IGenericBal<out T> where T : IEntity
{
IEnumerable<T> SearchByName(string name);
}
public class UserBal : IGenericBal<User>
{
private readonly IRepositoryDal<User> _userRepositoryDal;
public UserBal(IRepositoryDal<User> userRepositoryDal)
{
_userRepositoryDal = userRepositoryDal;
}
}
public interface IRepositoryDal<T> where T : IEntity
{
IEnumerable<T> SearchByName(string username);
T SearchById(string id);
void Update(T entity);
void Remove(T entity);
void Add(T entity);
}
public class UserRepositoryDal : IRepositoryDal<User>
{
private readonly IDbManager _dbManager;
public UserRepositoryDal(IDbManager dbManager)
{
//read from either singleton or configuration file !!
_dbManager = dbManager;
}
}
I tried to also make like this:
var container = new Container();
// Select the scoped lifestyle that is appropriate for the application
// you are building. For instance:
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
// DisposableService implements IDisposable
container.Register<FrmLogin>(Lifestyle.Scoped);
but then i get following error:
"SimpleInjector.DiagnosticVerificationException:
'The configuration is invalid. The following diagnostic warnings were
reported: -[Lifestyle Mismatch] FrmLogin (Async Scoped) depends on
IGenericBal implemented by UserBal (Transient). -[Lifestyle
Mismatch] FrmLogin (Async Scoped) depends on IGenericBal
implemented by OrderBal (Transient). See the Error property for detailed
information about the warnings. Please see simpleinjector.org/diagnostics how
Nowhere in the documentation SimpleInjector.Packaging is mentioned. This is quite deliberate, since Packaging is usefulness of Packaging is very limited, and its use should be avoided in general. But instead of ignoring it completely, the documentation should describe how and when to use it and when not to use it.
Here's a suggestion for what we should add:
Most applications don’t need packaging. Packinging, installers, modules, registries or whatever your container of choice calls such feature, is only useful in case you have your container configuration in assemblies that are not known at compile time. There is no benefit whatsoever in case your application’s composition root has a compile time reference to the assemblies that hold those registrations.
In case your composition root contains a compile time reference, you are much better of just componentizing your registrations by placing them into static methods and call those methods from your composition root. This gives you the same amount of componentization, while everything is visibly referenced from within the start-up path. In other words, you can F12 to those locations, while still being able to group things together.
Example:
public void App_Start()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
BusinessLayer.Bootstrapper.Bootstrap(container);
PresentationLayer.Bootstrapper.Bootstrap(container);
// add missing registrations here.
container.Verify();
}
Packaging features that most containers allow you to do the following (example using Castle):
var container = new WindsorContainer();
container.Install(new BusinessLayer.Bootstrapper());
This registration however has no benefit over calling a static method.
Containers often also allow you to load those packages using reflection, as does Simple Injector:
container.RegisterPackages(
from file in new DirectoryInfo(pluginDirectory).GetFiles()
where file.Extension.ToLower() == ".dll"
select Assembly.LoadFile(file.FullName));
But again, this is only useful when you require those assemblies to be loaded dynamically, which is something only few applications need. Downside of using this approach while having assemblies available during compile time, is that those packages are much less discoverable and it can easily fail at runtime, for instance because you forgot to mark the class with the required interface (in that case it will be skipped), or when the package doesn’t have a default constructor.
So again, unless you are loading assemblies (that contain container registrations) at runtime, you don’t need packaging.
The example tells you to use the following code
Registration registration = container.GetRegistration(typeof(IService)).Registration;
registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent);
but the call to SuppressDiagnosticWarning also requires a second input parameter with the reason for the suppression this seems wise but the example should be updated.
I think that it's important to clarify the cost of verify, it creates all actual types.
For large projects, it is not recommended for production.
The context-based injection examples in the advanced section lack an examplr of how you can select a registration based on the name of the ctor argument name.
It is saying "...An exception is thrown when a lifetime soped registration is requested outside of a scope instance.." (search by word soped for concrete place).
It should be saying "...An exception is thrown when a lifetime scoped registration is requested outside of a scope instance..." (soped -> scoped)
Hello,
I am a beginner and I am not familiar with the ASP.NET framework.
I think the quick start document started with a framework is not a good start :(
Users often don't realize that generic decorators are automatically applied conditionally based on their generic type constraints. Take this issue for instance. The documentation should make this nore clear.
There is currently no guidance on working with Console Applications. This should be added (and can be rather short).
For inspiration, see here.
Hi,
any pointers? I would like to inject the IMediator from mediatr into a signalr hub using simple injector but i cannot do it because there is no extension in SI to do it. I am more than willing to contribute but I am not sure what to do! Aspnet core 2.1
O
In the OWIN Integration Guide (under the section Extra Features), there is a code snippet to register the owin context with the following piece of code:
CallContextOwinContextAccessor.OwinContext = context;
context
has the type IOwinContext
and
CallContextOwinContextAccessor.OwinContext
has the type AsyncLocal<IOwinContext>
Obviously, the compiler does not like this.
A typical way of working with Simple Injector in Ambient Context-lacking applications (Read: Windows RT) is the following:
// Starting/ending scopes
using (var scope = new Scope(container))
{
// Attach runtime data to the scope to allow it to flow through the graph
scope.SetItem("requestId", Guid.NewGuid());
// Resolve directly from the scope:
var service = scope.GetInstance<IMyService>();
await service.DoYourThing();
}
// Using scopes
public class CommandDispatcher : ICommandDispatcher
{
private readonly Scope scope;
public CommandDispatcher(Scope scope) {
this.scope = scope;
}
public void Dispatch<T>(T command) {
// Services should again be resolved from the scope to continue flowing runtime data.
var handler = this.scope.GetInstance<ICommandHandler<T>>();
handler.Handle(new CommandEnvelope<T>(
// Runtime data can be retrieved from the Scope again by injecting it into an adapter:
requestId: (Guid)this.scope.GetItem("requestId"),
command: command));
}
}
The previous code enables flowing runtime data; in case components must be registered as scoped, a custom scoped lifestyle must be created (since Simple Injector doesn't have anything for this in the box):
sealed class NonAmbientScopedLifestyle : ScopedLifestyle
{
public NonAmbientScopedLifestyle() : base("Non-ambient Scoped") { }
protected override Func<Scope> CreateCurrentScopeProvider(Container c) {
return ThrowNotSupported;
}
[DebuggerStepThrough] private static Scope ThrowNotSupported() {
throw new NotSupportedException("You can't resolve directly from the container.");
}
}
// Registration
var container = new Container();
container.Options.DefaultScopedLifestyle = new NonAmbientScopedLifestyle();
container.Register<IUserContext, UserContext>(Lifestyle.Scoped);
In the section No out-of-the-box support for property injection there is a double-negative that is confusing and likely doesn't says what is expected.
The passage in question states
...in none of the cases the container doesn’t know if skipping the property...
From context I believe it should actually be something similar to
...in none of the cases does the container know if skipping the property...
The MVC integration docs https://simpleinjector.readthedocs.org/en/latest/mvcintegration.html example contains a call to the RegisterIntegratedMvcFilterProvider. Since DI in attributes is not adviced and not promoted, perhaps we should remove the call from the documentation.
While trying to understand the behaviour of the RegisterConditional call, we misinterpreted the documentation a little. There is a note in the docs:
Note: The predicates are only used during object graph compilation and the predicate’s result is burned in the structure of returned object graph. This disallows changing the graph based on runtime conditions.
We thought that this was obvious, as the resulting object graph would not change. What seems to happen though, is that the class graph is determined here as well and will not be reevaluated, which makes every following call with the same context to produce the same dependecy.
Is that correct?
If so, I would suggest changing the note like this:
Note: The predicates are only used during object graph compilation and the predicate’s result is burned in the structure of returned object graph. For a given resolution context, an object of the same type will be created on every subsequent call. This disallows changing the graph based on runtime conditions.
Does that make sense and does it reflect the actual behaviour? If so, I would create a pull request with the change.
I have read the WPF Integration docs and they tell me to do it like this (compact version shown):
static class Program
{
[STAThread]
static void Main()
{
var container = Bootstrap();
var app = new App();
var mainWindow = container.GetInstance<MainWindow>();
app.Run(mainWindow);
}
}
On the other hand, a StackOverflow guruThe Man recommends to override the App.OnStartup
event:
The appropriate entry point depends on the framework:
- In console applications it's the Main method
- In ASP.NET MVC applications it's global.asax and a custom IControllerFactory
- In WPF applications it's the Application.OnStartup method
- In WCF it's a custom ServiceHostFactory
etc.
(you can read more about framework-specific Composition Roots in chapter 7 of my book.)
I am, thus, using Simple Injector like this, with the same visible behaviour, and - IMO - a lot less invasiveness:
// after removing StartupUri from App.xaml...
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new BootStrapper();
MainWindow = bootstrapper.GetMainWindow();
MainWindow.Show();
}
}
Besides some minor variations, the whole point is the idea of not bypassing the normal WPF App instantiation, but instead just to override OnStartup
event.
What do you think of changing the documentation to reflect this?
Hello,
I followed your WPF user guide, but it doesn't show how to compose my MainWindow
with additional UserControls build via SimpleInjector DI. Having guessed, I tried injecting my control into the MainWindow
constructor and adding it to a Grid
like so, however I can't get the UserControl to appear. What is the correct way to compose UI elements via DI? (Main
is a Grid
)
<Window x:Class="Iwco.ManualDeploy.Client.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Converter"
MinWidth="300"
MinHeight="400"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight">
<Grid Name="Main">
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow(ConverterControl converterControl)
{
InitializeComponent();
Main.Children.Add(converterControl);
Main.UpdateLayout();
}
}
P.S. using <views: MyUserControl>
no longer works because my MyUserControl
constructor takes properties via DI.
Contrary to what's outlined here, RegisterExecutionContextScope
is not present in SimpleInjector.Extensions.ExecutionContextScoping (even in latest v2.8.0)
.
Is something amiss in the docs or is it no longer supported (the extension method)? Or is it something that's upcoming in v3?
Object browser confirms its absence:
Hey!
I've been reading the collections doc again because after the update it's obsolete.
There are several places in the documentation that says container.Register.Collection
instead of container.Collection.Register
.
Example Just search for register.collection and you'll find several places.
Thank you!
Hi,
Can you add a RegisterMvcControllers and RegisterMvcViewComponents overload that take assemblies or types.
This will enable adding registration in ConfigureServices. For assemblies it should scan for Microsoft.AspNetCore.Mvc.ControllerBase or ViewComponent in exported types.
Thanks
We should add information about how to deal with ExecutionEngineExceptions to the documentation. We can use the answer to this question somewhere in the documentation. Perhaps a new FAQ page?
The current copyright notice runs to 2017 and needs extending to encompass this and last year.
The context-based injection examples in the advanced section lack an examplr of how you can select a registration based on the name of the ctor argument name.
Describe when to use packaging and when not to use packaging, since packaging is only useful in situations where parts of the registrations are located into 'plugin' assemblies that are loaded at runtime (instead of being available during compile time).
When I copy and try to utilize the line:
// The following registers a Func<T> delegate that can be injected as singleton,
// and on invocation resolves a MVC IViewBufferScope service for that request.
container.RegisterSingleton<Func<IViewBufferScope>>(
app.GetRequestService<IViewBufferScope>);
from https://simpleinjector.readthedocs.io/en/latest/aspnetintegration.html
I get an error that the RegisterSingleton is ambiguous.
simpleinjector/SimpleInjector#403 .NET Junkie states that is a known compiler issue and gives an example for the specific case in question. Please update to what this should be in the docs. I have currently set mine to:
this.container.RegisterSingleton<IViewBufferScope>(app.GetRequestService<IViewBufferScope>());
but I am having other issues and I'm not sure that this is correct.
in the section
https://simpleinjector.readthedocs.io/en/latest/extensibility.html?highlight=initialize#overriding-property-injection-behavior
there are several instances text that renders as "Register Initialize r"
Simple Injector contains a Transient lifestyle, which is similar to Instance Per Dependency, but includes verification. A paragraph should be added that described what Instance Per Dependency is, why it is not included, and how you can add it.
In aspnetintegration.rst you provide a sample with a single middleware. If people are designing/writing middleware in their core flow, then they probably want them chained which is the default behavior with MS DI pattern. Something like the following is what I am doing. Please correct if not proper way of handling:
app.Use(async (context, next) =>
{
////The following is incorrect....
////await this.container.GetInstance<ErrorHandlingMiddleware>().Invoke(context, next);
////await this.container.GetInstance<SecurityHeaderMiddleware>().Invoke(context, next);
////This is the correct way.
await this.container
.GetInstance<ErrorHandlingMiddleware>()
.Invoke(context,
() => this.container
.GetInstance<SecurityHeaderMiddleware>()
.Invoke(context, next));
});
Promote this answer into official documentation for WinForms: https://stackoverflow.com/a/38421425/264697
Here's a list with things that should change for v4:
Fixed:
ServiceType
is marked Obsolete
and the https://simpleinjector.org/depr3 link is added. The documentation behind this link should be added.LifetimeScopeLifestyle
is renamed to ThreadScopedLifestyle
, the no-per-thread-lifestyle page should be updated to make it more clear that ThreadScopedLifestyle
is not the kind of lifestyle that is supported in that page.LifetimeScopeLifestyle
to ThreadScopedLifestyle
, this description can be confusing and needs updating.See: #82
See: simpleinjector/SimpleInjector#623
The docs on singleton state:
Note: Simple Injector will cache a Singleton instance for the lifetime of the Container instance and will dispose any auto-wired instance when Container.Dispose() is called. Instances that are not created by the container (and supplied to the container using
RegisterSingleton<TService>(TService)
will not be disposed by the container.
There is however a third registration that is not described, which is: RegisterSingleton<T>(Func<T>)
. The docs should clearly state whether or not objects created through the custom delegate are disposed or not.
Example: the table here: https://github.com/ninject/ninject/wiki/Object-Scopes.
Moved from here.
I am currently implementing plugins in my application using Simple Injector and it wasn't clear from the documentation how I could generate many instances of the same plugin without relying on the Container
itself.
I finally found what the information I was looking for in this answer, that IEnumerable<IPlugin>
gives you a new instance every time it is iterated through.
I believe it would be useful to other users if this information (as sample code maybe ?) was available with the Package registrations documentation and/or Registering plugins dynamically.
In the end, I was able to find that behavior described in the Collection types documentation but only because I knew what I was looking for after reading your answer on StackOverflow...
Hello. I'm involved in a web project where we use Simple Injector.
In this project we need to access the request (HttpRequestMessage
) in several places. One such location is in the logging service. When the api receives a request, a CorrelationId
is injected into the request header which we can then use throughout the request to log. We are unable to access the request in all locations and we think that the topic "Getting the current request's HttpRequestMessage" in your documentation would help but we are not achieving the desired result.
Can you help?
I send a small project that exemplifies what we want.
After compiling just run and access the addresses: http://localhost:53983/api/v1/about
Thanks for any help you can give.
The mixing-collections-of-open-generic-and-non-generic-components page shows the following example:
List<Type> typesToRegister = new List<Type> {
typeof(DataAnnotationsValidator<>)
};
var assemblies = new[] { typeof(IValidator<>).Assembly) };
typesToRegister.AddRange(container.GetTypesToRegister(typeof(IValidator<>), assemblies));
container.RegisterCollection(typeof(IValidator<>), typesToRegister);
The example can be simplified by using the TypesToRegisterOptions
that has been around for quite some time already:
var assemblies = new[] { typeof(IValidator<>).Assembly) };
var typesToRegister= container.GetTypesToRegister(typeof(IValidator<>), assemblies,
new TypesToRegisterOptions { IncludeGenericTypeDefinitions = true });
container.RegisterCollection(typeof(IValidator<>), typesToRegister);
Hi,
I wrote some info how to use the container in XAML.
Please add it to wpfintegration.rst
Thanks,
Mikhail
Using Markup Extention we can request instances directly in XAML
.. code-block:: c#
using System;
using System.Windows.Markup;
namespace Lipro.Base
{
//
// Markup extension that resolves an instance from the IoC container.
// Based on Mike Hillberg's Blog on Wpf and Silverlight
// http://blogs.msdn.com/b/mikehillberg/archive/2006/10/06/limitedgenericssupportinxaml.aspx
//
[ContentProperty("TypeArguments")]
public class ContainerExtension : MarkupExtension
{
public Type Type { get; set; }
public ContainerExtension()
{ }
// ProvideValue, which returns an object instance from the container
public override object ProvideValue(IServiceProvider serviceProvider)
{
// Use the weakly typed version to get the instance
return IoC.Instance.GetInstance(Type);
}
}
}
Set the ViewModel in XAML
.. code-block:: xaml
<Window.DataContext>
<base:Container Type="{x:Type viewModels:MyViewModel}"/>
</Window.DataContext>
Binding to Static Resource
.. code-block:: xaml
<UserControl.Resources>
<base:Container Type="{x:Type viewModels:MyViewModel}" x:Key="viewModel"/>
</UserControl.Resources>
<TextBox Text="{Binding Source={StaticResource viewModel}, Path=Name}"
Many of the best practices are scattered throughout the documentation and articles across the internet. These best practices should be summarized in one wiki page, while linking to the complete articles when needed.
The documentation gives an example of how to use Simple Injector in WinForms projects. The example shows the code for the main view/main form with only a DI constructor.
The problem is, that the code as given throws an exception in one of the SI lines stating that the main view requires a parameterless constructor!
If I put the default constructor then the form does not work well.
The Contextual Binding section of the documentation just gives one (rather complex) example; more examples are required.
Hey.
I have found the documentation
And it said that
Reverting to the Service Locator pattern means that you need to do the following:
- Extract all the attribute’s logic -with its dependencies- into a new service class.
- Resolve this service from within the filter attribute’s OnActionExecXXX methods, but don’t store the resolved service in a private field.
- Call the service’s method.
Could you give more explanation about why I should not do it? Thanks.
SimpleInjector 4 has removed the CLSCompliant
attribute from the assembly! Please consider adding it again.
Could you add an integration package for SignalR using the following source code?
file SimpleInjectorSignalRDependencyResolver.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.SignalR;
namespace SimpleInjector.Integration.SignalR
{
public class SimpleInjectorSignalRDependencyResolver : DefaultDependencyResolver
{
public SimpleInjectorSignalRDependencyResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public override object GetService(Type serviceType)
{
return _serviceProvider.GetService(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var @this = (IEnumerable<object>) _serviceProvider.GetService(typeof (IEnumerable<>).MakeGenericType(serviceType));
var @base = base.GetServices(serviceType);
return @this == null ? @base : @base == null ? @this : @this.Concat(@base);
}
private readonly IServiceProvider _serviceProvider;
}
}
file SimpleInjectorHubDispatcher.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace SimpleInjector.Integration.SignalR
{
public class SimpleInjectorHubDispatcher : HubDispatcher
{
public SimpleInjectorHubDispatcher(Container container, HubConfiguration configuration) : base(configuration)
{
_container = container;
}
protected override Task OnConnected(IRequest request, string connectionId)
{
return Invoke(() => base.OnConnected(request, connectionId));
}
protected override Task OnReceived(IRequest request, string connectionId, string data)
{
return Invoke(() => base.OnReceived(request, connectionId, data));
}
protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
{
return Invoke(() => base.OnDisconnected(request, connectionId, stopCalled));
}
protected override Task OnReconnected(IRequest request, string connectionId)
{
return Invoke(() => base.OnReconnected(request, connectionId));
}
private async Task Invoke(Func<Task> method)
{
using (_container.BeginExecutionContextScope())
await method();
}
private readonly Container _container;
}
}
Registration sample:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.Register<DbContext, MyDbContext>(Lifestyle.Scoped);
container.Register<ISampleRepository, SampleRepository>(Lifestyle.Scoped);
// if you want to use the same container in WebApi don't forget to add
app.Use(async (context, next) => {
using (container.BeginExecutionContextScope())
await next();
});
// ... configure web api
var config = new HubConfiguration
{
Resolver = new SimpleInjectorSignalRDependencyResolver(container)
}
// ... configure the rest of SignalR
// important to pass SimpleInjectorHubDispatcher
app.MapSignalR<SimpleInjectorHubDispatcher>("/signalr", config);
}
}
P.S. I tried to make a PR but experienced problems with the project solution in my dev environment.
SimpleInjector.Integration.WebApi.WebHost.QuickStart
package has a framework reference to Microsoft.Web.Infrastructure
. As far as I know, the Infrastructure assembly is a NuGet package - in other words not part of the GAC.
See my issue here:
https://stackoverflow.com/questions/48580482/unable-to-install-nuget-pck-microsoft-web-infrastructure-is-not-in-my-gac
Please correct me if I'm wrong.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.