keboo / autodi Goto Github PK
View Code? Open in Web Editor NEWDependency injection made simple.
License: MIT License
Dependency injection made simple.
License: MIT License
It would be nice to have a simple example using AutoFac, similar to the StructureMap and MS thirdParty examples.
A simple dotnet core console application similar to the projects here and here. The AutoFac example should also be in the /Examples/ThirdParty directory (like those two examples).
Rather than creating a separate project (like what I did with StructureMap.AutoDI), I think it would be cleaner to just create an AutoFac equivelent of ApplicationBuilderMixins directly inside the example dotnet core console application rather than in a separate project. I am assuming we can simply add a reference to the Autofac.Extensions.DependencyInjection
package and use the classes in there to get similar results.
Also note that examples are being moved to the wiki so this is where the documentation should go.
Current there is no way to register open generics.
Consider a simple case using Microsoft.Extensions.Logging.
Ideally I would like to write the following code
public class MyClass
{
public MyClass([Dependency] ILogger<MyClass> logger = null) { ... }
}
This poses a problem for registering because we currently only resolve closed generics. What I would like is some way to register a factory method for the open generic.
Something like:
ContainerMap map = ...;
map.AddLazySingleton(genericTypes => GetLogger(genericTypes[0]), new[] {typeof(ILogger<>});
//In ContainerMap
public void AddLazySingleton(Func<Type[], object> genericCreate, Type[] keys) { ... }
During resolution this would change the logic to be:
Currently the API is a bit clunky to work with.
Need to add some cleaner methods for:
All of the projects in the Examples should be updated to the latest 3.0.0 NuGet release of AutoDI.
This should come from release on nuget.org.
As part of #20 we want to allow for classes to manually specify that they want an IDependencyResolver
or similar. We should pass in the current resolver for this parameter.
This needs testing to confirm.
When merging AutoDI and AutoDI.Container the code for processing dependent assemblies for types also got merged. In some cases this is fine, as it lets both work together to build up mappings for types. However, Fody handles re-signing the assembly that the weaver processed; which is great. However if we are going to also modify the dependent assemblies we likely need to handle re-signing those assemblies as well.
This might also be solved by having a weaver that runs on the assemblies after AutoDI to force Fody to do the signing for us.
Currently the container simply returns default(T) when it is unable to locate a dependency.
The ContainerMap (also added to IContainer interface) should have an event that is raised when a service type key is not found to allow for a caller to either fill the dependency, log a failure message, or even throw an exception (if that is the desired behavior).
Currently to modify the container's map at run time requires a reflection call. Though this is fine for testing the mapping in unit tests, it would be much nicer if the weaver would simply looking for a method like this:
[AutoDI.Container.SetupMethod]
private static void ContainerSetup(ContainerMap map)
{
}
The method must be static.
The method must reside in the main module of the assembly with the generated container (this allows for the method to be either public or non-public).
The method must accept a single ContainerMap
parameter.
The method must be decorated with the AutoDI.Container.SetupMethod.
The method should be invoked by the generated container after it has added everything to the map. This will allow the caller greater control over the contents of the map. This means that it may be invoked prior to any user code.
In addition it would be nice to clean up the ContainerMap API to make it a bit friendlier to work with.
This appears to be an issue with release version 2..1.0
There should be an overload to DependencyResolver.Set that takes in an IDependencyResolverBehavior. This interface should have a single member that mirrors DependencyResolver.Get()
:
IDependencyResolver Get()
This will allow for callers to define additional logic for determining what IDependencyResolver instance gets returned. This will also lay the groundwork for leveraging nested DI containers.
It would be nice to be able to write LINQ queries against the container to get all items of a given type (such as IDisposable).
By default these should not create instances; rather they should only return the instances that have already been created. Attaching the CreateInstances() into the expression would for creations of instances.
Perhaps something like this:
IContainer map = ...;
IEnumerable<IDisposable> disposableSingletons = map.Singletons().OfType<IDisposable>();
//Typically you would not need to add CreateInstances() to the Singleton enumeration (because the instances are always created). However because the singletons are not created until AFTER the setup method you may need to add it if you want to use this inside of the SetupMethod. (see issue 49)
IEnumerable<IDisposable> aliveDisposableLazySingletons = map.LazySingletons().OfType<IDisposble>();
IEnumerable<IDisposable> allDisposableLazySingletons = map.LazySingletons().CreateInstances().OfType<IDisposble>();
IEnumerable<IDisposable> createdWeakTransients = map.WeakTransients().OfType<IDispoable>();
IEnumerable<IDisposable> allWeakTransients = map.WeakTransients().CreateInstances().OfType<IDispoable>();
//For now simply ignore transient instances since working with them would require tracking all instances generated.
The AutoDI weaver should be available as a nuget package.
Currently these are just being uploaded to appveyor. It would be nice to have a mechanism to post nightly preview packages to nuget.org too.
Because the singletons are evaluated before any run-time dependencies can be added there is no way for AutoDI to have a Singleton with a run-time dependency.
I think the best way to handle this is to not invoke the Setup Method until after the container has been initialized as set as the default resolver. This allows for code inside of the Setup method to act the on the ContainerMap
.
Calling the SetupMethod from inside of the constructor means that it is not set as the default resolver and thus you cannot resolve dependencies from the container.
Currently the IDependencyResolver only has a single Resolve method.
It should be possible to also have a non-generic overload.
Currently working around it with this extension method.
public static class AutoDIMixins
{
public static object Resolve(this IDependencyResolver resolver, Type targetType)
{
var methodInfo = typeof(IDependencyResolver).GetMethod(nameof(IDependencyResolver.Resolve));
methodInfo = methodInfo.MakeGenericMethod(targetType);
return methodInfo.Invoke(resolver, new object[] { new object[0] });
}
}
Currently it is possible to pass values from the DependencyAttribute, however these values are being dropped at the AutoDIServiceProvider
This should be done in two ways. First set the default behavior in Fody. Allow for overriding this default on specific types with an attribute.
There are several TODOs in the DI class. When the operations fail it is currently throwing an InvalidOperationException for all failures.
What needs to be done is create three specific exception types to provide more clarity on exactly which issue occurred.
Currently all of the exceptions are stored in the AutoDIException.cs file. All of the created exceptions should derive from AutoDIException.
Remove the TODO comments and replace with the following exceptions in the DI class:
RequiredMethodMissingException - throw this exception in all of the cases where it fails to find the expected method on the generated type.
GeneratedClassMissingException - throw this exception in the case when the generated AutoDI type is not found.
GlobalServiceProviderNotFoundException - throw this exception when the global service provider field is not found on the generated type.
The GlobalDI class currently has a single T GetService<T>(object[])
method. This method simply wrapps calls into IServiceProvider.GetService
.
The following overloads should be added:
T GetService<T>()
- this should simply call the original method passing an empty array for the parameters.object GetService(Type serviceType, object[] parameters)
- Same as the original method but should call the non-generic version of the IServiceProvider.GetService
method.object GetService(Type serviceType)
- Should call the method above passing an empty array for the parameters.I think the issue is the lack of pdb file being in included in the nuget.
https://oren.codes/2015/09/23/enabling-source-code-debugging-for-your-nuget-packages-with-gitlink/
From Gitter chat:
Geert van Horrik
the readme references the unstable packages (develop branch)
it's on the list to be released as stable, but I just have too much to do at the moment to release it as stable, maybe next week
Andrew Arnott
install the v3 prerelease to get msbuild integration for free. Yes, it works with .NET SDK projects.
Request for Kelly to allow for property injection.
Because we resolve the dependencies inside of the constructor this should also work with readonly properties as well.
When adding AutoDI.Fody nuget package. The AutoDI.dll is set as a reference but it is not marked as copy local. In addition on ClickOnce deployed apps it is setup as a Prerequisite.
Working idea 2
//IScope derives from IDisposable so you can clean up and tell it when scope is done.
IScope @global = AutoDI.Scope.Global;
IScope nested = @global.CreateNested();
var controller = nested.Resolve<Controller>();
public interface IService {}
public class Service : IService {}
public class Controller
{
public Controller([Dependency]IService service = null)
{ }
}
In short remove most of the magic and work exactly like the other containers (at least in terms of nesting, and the code that you write).
Some small bits of magic:
public class Controller
{
[Dependency]
private IService Service{ get; }
public Controller([Dependency]IOther other = null)
{ }
}
=>
public class Controller
{
[Dependency]
private IService Service{ get; }
//Using generated class as last parameter to ensure no collisions.
public Controller(IScope <scope>, IOther other, <AutoDIGenerated> unused)
{
Service = <scope>.Resolve<IService>();
this(other);
}
public Controller([Dependency] IOther other = null)
{ }
}
Right now the config supports lots of regex matching patterns which is great, but is more complicated than necessary.
This change is expected to be a breaking API change. Backward compatibility is not required or expected.
Some suggestions for a better API:
regex:
in order to get regex match. Otherwise simple contains style matching with wildcards *
will do. Yes this is a breaking change.map
and type
nodes.Currently there is no way to pass a parameter to the IDependencyReoslver.Resolve
method. Many DI containers support registering and resolving dependencies with keys or other custom parameters. Ideally these parameters would be specified on the DependencyAttribute
This is the last piece to letting Singletons be automatically generated when they have run-time dependencies.
The container should add them as Func, but after the setup method is invoke it should create all of the singleton instances.
The setup method only appears to get invoked when it is public.
It should also allow internal as well since it will be in the same module as the generated container.
Currently the weaver is assuming that null will be the default value of the dependency and comparing against null when determining if the dependency was provided by the caller. Though this will likely be correct in most case the weaver should use the default value specified on the parameter rather than assuming null.
There should be one package for Fody and one for just the AutoDI lib. This is useful for unit tests that want to test an assembly that is using the AutoDI IL weaver but don't need to take a dependency on Fody itself.
When used on a WPF.exe it appears to break the debugger.
Right now there is a ThirdParty directory at the root of the repository. This should be merged into the Examples\ThirdParty directory and the appropriate project references updated.
Currently the weaver just logs warnings to the output window. This is ok, but it would be better to log with the sequence point so the user can simply click the warning to navigate.
The LogError and LogWarning delegate properties have an additional overload that also logs the sequence point. AutoDI should be calling these overloads and including the sequence points so it is obvious where the problems are located.
At a minimum, all the error/warning messages should indicate at least the file, and enough information so the offending code can be easily located.
There is also the MSBuild logging verbosity. But rather than cluttering that up it would be nice if there was an additional setting for the weavers to control how much output they produce.
Rather than maintaining release notes in the nuspec files we should remove the <releaseNotes>
tag and append the following to all of the <description>
tags.
Release notes: https://github.com/Keboo/AutoDI/wiki/Release-Notes
This will be a breaking change, but since the AutoDI.Container depends on AutoDI to function properly it would be better to have a single weaver that can be configured rather than two weavers.
This will mean the AutoDI weaver will need a configuration switch to disable generation of the container. This switch should default on however, since the goal is to make AutoDI a single install nuget and things just work the way you expect solution. Integrating with your own DI container already requires coding.
Basic coding guidelines.
Add support to the AutoDI.Container.ContainerMap when a key is of type Lazy if no key is found, but a key for T is found, build up a new Lazy instance that resolves by retrieving the T from the map.
Add a property to the ContainerMap to disable this feature, it should default to true, however.
Add configuration support to also disable this feature.
We want to allow passing parameters to to the DependencyResolver.Get()
method to allow for more flexibility when determining what resolver to return.
Ideally there will be an attribute that can be used on the constructor or class that will allow for setting additional information that is passed to the method.
Because of casing there are now two "nuget" folders in the repo. This needs to be cleaned up.
The nuspec files need to properly specify a max version. I am thinking that given the number of breaking changes likely to be introduced, it would be best to do something like: version="[2.1,2.2)"
Currently AutoDI is targeting the latest .NET framework. This make the it less available to people who cannot simply update their .NET version. Change the .NET version to be the lowest possible.
Right now the README has nothing useful in it.
Right now there are a fixed number of hard coded behaviors. It would be nice if it were possible to declare a custom behavior (in either a dll, or directly inside of the project) and have it run as part of the weaver.
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.