Giter Club home page Giter Club logo

documentation's Introduction

Documentation

documentation's People

Contributors

alexfoxgill avatar batsihor avatar bouke avatar compilenix avatar dotnetjunkie avatar fdudannychen avatar ganchito55 avatar giuliocaccin avatar jan-oratowski avatar joshball avatar joshmccullough avatar khellang avatar kwlin avatar lgirvin avatar mikelooper avatar mindmat avatar omarjuul avatar pavlalexandr avatar perlun avatar philippemercure avatar qujck avatar rexcfnghk avatar rold2007 avatar sammurray381 avatar scottyscooter avatar seangwright avatar simpleinjector avatar stevenrobertscrew avatar thebigric avatar uriel6575 avatar

Stargazers

 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

documentation's Issues

Clarification on RegisterConditional

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.

AspNetCore Doc Issue

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.

WPF: How do I compose UI elements via DI?

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.

Add example of TypesToRegisterOptions

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);

SignalR Hub injection

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

Add information about working in applications that lack Ambient Context

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);

Add 'best practices' page to documentation

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.

"Register.Collection" instead of "Collection.Register"

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!

SimpleInjector.DiagnosticVerificationException

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

OWIN Integration Guide: owin context registration

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.

v4 documentation changes

Here's a list with things that should change for v4:

Fixed:

  • Because of the changes with issue 348 the ServiceType is marked Obsolete and the https://simpleinjector.org/depr3 link is added. The documentation behind this link should be added.
  • Since 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.
  • Because of a rename of LifetimeScopeLifestyle to ThreadScopedLifestyle, this description can be confusing and needs updating.

Add docmentation section about packaging

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).

Misprint at Object Lifetime Management page

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)

Information missing about disposable in docs

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.

Suggestion: Document how to chain middleware request pipeline

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));
});

SignalR integration

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.

GetCurrentHttpRequestMessage

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.

GetCurrentHttpRequestMessage.zip

WinForms problem with main view using DI

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.

Update copyright

The current copyright notice runs to 2017 and needs extending to encompass this and last year.

Addition to the Windows Presentation Foundation Integration Guide

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}" 

Error in disposabletransientcomponent.html

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.

Question: Why I should not store the resolved service in a private field in filter attributes?

Hey.

I have found the documentation

https://simpleinjector.readthedocs.io/en/latest/webapiintegration.html#injecting-dependencies-into-web-api-filter-attributes

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.

Add documentation about Packaging

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.

IOptions commentary

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

WPF integration recipe - maybe there's a better way?

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?

Documentation improvement for plugins

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...

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.