dadhi / dryioc Goto Github PK
View Code? Open in Web Editor NEWDryIoc is fast, small, full-featured IoC Container for .NET
License: MIT License
DryIoc is fast, small, full-featured IoC Container for .NET
License: MIT License
My type definition:
public interface ITestInterface<TKey>
{
}
public abstract class AbsTestClass<TKey> : ITestInterface<TKey>
{
}
public class TestClass<TKey> : AbsTestClass<string>
{
}
I use it like this:
var c = new Container(r=>r.WithTrackingDisposableTransients());
c.Register(typeof(ITestInterface<>),typeof(TestClass<>),Reuse.Singleton);
However, he seems to be unable to work, prompting the following exception information:
DryIoc.ContainerException: Registering implementation type ConsoleApp1.TestClass<> is not assignable to service type ConsoleApp1.ITestInterface<>.
at DryIoc.Throw.It(Int32 error, Object arg0, Object arg1, Object arg2, Object arg3) in D:\Dev\DryIoc\src\DryIoc\Container.cs:9491
at DryIoc.ReflectionFactory.ThrowIfImplementationAndServiceTypeParamsDontMatch(Type implType, Type serviceType) in D:\Dev\DryIoc\src\DryIoc\Container.cs:7548
at DryIoc.ReflectionFactory.ThrowIfInvalidRegistration(Type serviceType, Object serviceKey, Boolean isStaticallyChecked, Rules rules) in D:\Dev\DryIoc\src\DryIoc\Container.cs:7516
at DryIoc.Container.Register(Factory factory, Type serviceType, Object serviceKey, Nullable`1 ifAlreadyRegistered, Boolean isStaticallyChecked) in D:\Dev\DryIoc\src\DryIoc\Container.cs:177
at DryIoc.Registrator.Register(IRegistrator registrator, Type serviceType, Type implementationType, IReuse reuse, Made made, Setup setup, Nullable`1 ifAlreadyRegistered, Object serviceKey) in D:\Dev\DryIoc\src\DryIoc\Container.cs:4534
at ConsoleApp1.Program.Main(String[] args) in E:\Tes\PRoject\2018.11.10\ConsoleApp1\ConsoleApp1\Program.cs:43
Something like this will do
var c = new Container(rules => rules.WithoutFastExpressionCompiler());
Currently there is only one resolution cache and it is located in root container. OpenScope
does not create its own.
This inflicts number of problems with scope (name) drpendent services, e.g. we need different implementations for scoped and singleton service, or between different named scopes. To solve it we fallback to more powerful but slow context aware Resolve(...Request preResolveParent,...)
and keyed resolution cache.
The new idea is to have cache-like structure with the root cache and multiple scope caches. Each scope cache will contain delegates resolved in scope, and the cache will be identifed by whole nested scopes route, e.g. "/*/*/name/*"
. Then OpenScope
will set the matching scope cache as default to look for, or will create a new scope cache for the first time.
Goals:
Avoid real performance regressions
Automate testing without false positives
Allow to experiment with improvement against self.
Provide other containers with exampele of testing and containers to live longer against pure functional composition.
Allow reasonably measure implementation of https://bitbucket.org/dadhi/dryioc/issues/197
Means:
Will not:
Links:
I've been using the auto-mocking code at:
UsingInTestsWithMockingLibrary
However, each instance it creates using NSubstitute is transient; I would like to reuse the same substitute object however I resolve it within the scope.
I've attached the code I came up with; I created a Dictionary indexed by Type to hold all the NSubstitute instances I created. But this feels like reinventing the wheel, isn't this something the container should do?
Am I missing a way to make WithUnknownServiceResolvers store the created object at SingletonOrScoped in the container on first creation?
public static IContainer WithNSubstituteFallback(this IContainer container, IReuse reuse = null)
{
// Cache all the NSubstitute instances we create by Type.
container
.ThrowIfNull()
.Register<INSubstituteInstanceCache, NSubstituteInstanceCache>(reuse ?? Reuse.ScopedOrSingleton);
return container.With(rules =>
{
return rules
.WithUnknownServiceResolvers(request =>
{
var serviceType = request.ServiceType;
if(!serviceType.IsAbstract)
return null; // Mock interface or abstract class only.
// resolveNSubstitute() will be called each time we try to resolve a missing
// type, so we use the cache to reuse the substitutes we've already created.
// Pass serviceType to arg0, resolve the cache in arg1.
return new ReflectionFactory(
made: Made.Of(
() => resolveNSubstitute(
Arg.Index<Type>(0),
Arg.Of<INSubstituteInstanceCache>()
),
_ => serviceType
)
);
});
});
}
private static object resolveNSubstitute(Type t, INSubstituteInstanceCache cache)
{
return cache.Resolve(t);
}
public class NSubstituteInstanceCache : INSubstituteInstanceCache
{
private readonly ConcurrentDictionary<Type, object> dict = new ConcurrentDictionary<Type, object>();
public object Resolve(Type t) => dict.GetOrAdd(t, _ => Substitute.For(new Type[] { t }, (object[])null));
}
public interface INSubstituteInstanceCache
{
object Resolve(Type t);
}
I'm looking at https://github.com/dadhi/DryIoc/tree/master/src/DryIocZero.WebApi
Seems like this is what I need but is there any sample on using it? Can't see any in documentation.
Basics would be how do I setup WebAPI to use IoC and how do I add dependencies (I guess in .ttinclude file?)
Idea is to have fast first-time (cold start) performance, and compile and cache the expression in parallel to have a later fastest performance.
Assumptions:
Activator.CreateInstance
much faster than Expression.Compile
.Compile
+ cachingIf the assumptions are true, we may try do both the expression creation and Activator.CreateInstance
. Then schedule expression to ThreadPool and return activated instance right away.
Originally from BitBucket, because I love the idea to migrate to GitHub:
https://bitbucket.org/dadhi/dryioc/issues/597/validate-call-fails-with-opengeneric
Cons:
Cons:
Give me your likes or dislikes :)
After one week of investigations we found out, that DryIoc 3.0.2 is rather slow in comparison to 2.12.8 at the first execution time (cold start). In most cases the first call of a C# application doesn't count. But we measured a time increase of ca. six seconds for greater object graphs in our application. So for example our asp.net core 2.1 application starts, DryIoc resolves some small Services, than the applications tries to resolve a controller and .. we can make a cup of coffee. For a web applications this is just uncomfortable (because after the JIT compiling it's fast), but for one of our console applications this is really painful.
We looked at the expression trees which dryioc generates in version 3.0.2 and 2.12.8 for one of our object graphs. Too much to post here and to analyze in depth, but we can say, that the dryioc 3.0.2 expression tree is roundabout 90% bigger and seems even more complex.
We didn't changed the service registrations much. We just replaced Reuse.InWebrequest through Reuse.Scoped and two RegisterDelegates through RegisterMany as you mentioned out here.
Maybe you can say more about this? In most of the cases we use simple service registrations like Register<IA, A>
, or factories, or made: Parameters.Of.Type
... We also use the IEnumerable
-resolve Feature.
Currently it does nothing if no registration was made, when no implementation and no service types to register were detected.
This seems wrong, as the User expects the method to do something.
Throwing the exception in this case may be a breaking, but better to inform the User earlier than to keep a silence and got an eventual surprise later.
DryIoc 3.1 Preview 4 throws a ContainerException
Exception with error Code RegisteredFactoryMethodResultTypesIsNotAssignableToImplementationType
, because the ThrowIfNotImplementedBy
-Method just checks with the C# reflection Method IsAssignableTo
, which ignores implicit cast operators.
Is this behavior expected?
Maybe a better check method would be:
public static bool IsCastableTo(this Type aFrom, Type aTo)
{
if(aFrom == null || aTo == null)
{
return false;
}
if (aTo.IsAssignableFrom(aFrom))
{
return true;
}
return aFrom.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.ReturnType == aTo)
.Where(m => m.Name == "op_Implicit" || m.Name == "op_Explicit")
.Any();
}
As part of my learning as how Unity3D works I will create unity package for your consideration and try run hello world
with it.
https://www.red-gate.com/simple-talk/dotnet/c-programming/extending-unity-editor-c/
http://hololenshelpwebsite.com/Blog/EntryId/3/Unity-5-Hello-World
In order to provide more clues for problem solution, we need to include as much context as possible (keeping performance constraints).
In V3 I have removed Expression level cache stored once per Factory. This simlified a problem with condition based resolution, and removed a whole lot of adhoc checks.
Memoize the built dependency expression into resolution root Request
by the FactoryId
. Exluding wrappers. Use the memoized expression instead of building a new one.
For open-generics we will use id of closed factory.
It is not a cache, cause it will be dropped when result expression is build and compiled.
This is similar to storing expression in a local var
and using this var multiple times to build the result.
Hello,
I have the following two classes I use for notifications:
public class InventoryNotificationBase : INotification
{
}
public class InventoryNotificationReceived : InventoryNotificationBase, INotification
{
}
And here is my handler:
public class InventoryDenormalizer :
INotificationHandler<InventoryNotificationBase>,
INotificationHandler<InventoryNotificationReceived>
{
public Task Handle(InventoryNotificationReceived notification, CancellationToken cancellationToken)
{
return Task.CompletedTask; // This is called twice.
}
public Task Handle(InventoryNotificationBase notification, CancellationToken cancellationToken)
{
return Task.CompletedTask; // This is never called.
}
}
Here is the publishing code:
mediator.Publish(new InventoryNotificationReceived());
The behavior I am noticing is the INotificationHandler<InventoryNotificationReceived>
is being called twice and the INotificationHandler<InventoryNotificationBase>
is never called.
However, I would have expected each handler to have been called once.
Thoughts?
Thanks for the awesome DI Container!
I have the following classes:
public interface IValidator { }
public interface IValidator<T>:IValidator { }
public class AbstractValidator<T> : IValidator<T> { }
public class SignInViewModel {
public SignInViewModel(IValidator validator) { }
}
public class SignUpViewModel {
public SignUpViewModel(IValidator validator) { }
}
How can I configure registration to achive injection of IValidator<SignInViewModel>
in SignInViewModel
and IValidator<SignUpViewModel>
into SignUpViewModel
accordingly?
It's super easy in SimpleInjector:
container.RegisterConditional(
typeof(IValidator),
c => typeof(AbstractValidator<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
I'm not sure what is the best way to achieve what I am trying to accomplish so let me give you an example.
I am using Azure Functions, which are stateless, with the following signature.
public static Task Run(Message message, ILogger logger)
{
var controller = Main.Container.Resolve<CsoConsumerController>();
// How can I attach the passed in logger instance so the rest of the services for the current flow re-use this instance?
return controller.Execute(message);
}
As you can see, the azure function framework passes me an instance of the ILogger already configured and initialized for this function call ONLY.
I read through the documentation and I think I need a new scope here but I'm not sure. I only want this ILogger instance to be used during the async execution of this one method call. Each function call will use their own.
Any help would be great?
I have two definitions of tool classes:
public interface ITool
{
void Print();
}
public class Tool : ITool
{
public void Print()
{
Console.WriteLine("I'm Tool.");
}
}
public class DefaultTool : ITool
{
public void Print()
{
Console.WriteLine("Null.");
}
}
Interceptor definition:
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("At Interceptor ...");
}
}
I injected the tool class as an attribute, but the parsed behavior is completely different:
public interface IApplicationImpl
{
void UseTool();
}
public class ApplicationImpl :IApplicationImpl
{
public ITool Tool { get; set; }
public ApplicationImpl()
{
Tool = new DefaultTool();
}
public void UseTool()
{
Tool.Print();
}
}
I did this test:
class Program
{
static void Main(string[] args)
{
var c = new Container(r=>r.WithTrackingDisposableTransients());
c.Register<ITool,Tool>();
c.Register<TestInterceptor>();
c.RegisterMany(new[]{typeof(IApplicationImpl),typeof(ApplicationImpl)},typeof(ApplicationImpl),Reuse.Transient,PropertiesAndFields.Auto);
c.Intercept<ApplicationImpl,TestInterceptor>();
// no.1
c.Resolve<IApplicationImpl>().UseTool();
// no.2
c.Resolve<ApplicationImpl>().UseTool();
Console.ReadKey();
}
}
Hi,
would it be possible to add New() method to IResolver or IResolverContext interface?
In DryIoc 2.x IContainer interface was used for containers and opened scopes, so code, that only had access to opened scope, could still create objects by calling New(). DryIoc 3.x now returns IResolverContext after opening scope, and there is no way to create an object without previous registration.
Example code that was valid in DryIoc 2.x, but not in DryIoc 3.x:
var container = new Container();
container.Register<Dependency>();
using (var scope = container.OpenScope())
{
//somewhere deep in the code, where container value is not available
scope.New<Object>();
}
Thanks for the great library.
Follows the error in the comment,
I suppose that I must register something regarding that function: Func<String, Microsoft.Extensions.Logging.LogLevel, Boolean>. Can you guys provide me some direction? =)
Btw, I am using DryIoc 3.0.2 and DryIoc.Microsoft.DependencyInjection 2.1.0.
// DryIoc.ContainerException: 'Unable to get constructor of Boolean using provided constructor selector when resolving Boolean {ReturnDefault} #571 with args [_String0]
//in wrapper Func<String, Microsoft.Extensions.Logging.LogLevel, Boolean> { ReturnDefault} as parameter "filter" #11 with args [_String0]
//in singleton Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider: Microsoft.Extensions.Logging.ILoggerProvider { ServiceKey = DefaultKey(0), ReturnDefault} #56
//in wrapper IEnumerable<Microsoft.Extensions.Logging.ILoggerProvider> { ReturnDefault} as parameter "providers" #1
//in singleton Microsoft.Extensions.Logging.LoggerFactory: Microsoft.Extensions.Logging.ILoggerFactory as parameter "factory" #42
//in singleton Microsoft.Extensions.Logging.Logger<Microsoft.AspNetCore.Hosting.Internal.WebHost>: Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Hosting.Internal.WebHost> #570
//from container.
// Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(
Configuration.GetConnectionString("DataBaseIntranetCore")));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
return services.ConfigureDI(Bootstrap.RegisterServices);
}
// IocDiExtensions.cs
public static class IocDiExtensions
{
public static IServiceProvider ConfigureDI(this IServiceCollection serviceCollection, Action<IRegistrator> configureServices)
{
var container = new Container(rules => rules
.WithoutThrowOnRegisteringDisposableTransient()
.WithTrackingDisposableTransients()
.WithAutoConcreteTypeResolution())
.WithDependencyInjectionAdapter(serviceCollection);
container.UseInstance(container);
configureServices(container);
return container.Resolve<IServiceProvider>();
}
}
// Bootstrap
public static void RegisterServices(IRegistrator registrator)
{
// ILogger here is something I made, is not the same from Microsoft.Extensions.Logging.ILogger
registrator.Register<ILogger, LogWrapper>(Reuse.Transient);
registrator.Register<IAppConfig, AppConfig>(Reuse.Transient);
registrator.Register<ICoreDbContext>(made: Made.Of(() => new CoreDbContext()));
registrator.Register<ICoreDbContext>(made: Made.Of(() => new CoreDbContext("DataBaseCoreRO")), serviceKey: "ReadOnly");
registrator.Register<IContextFactory, ContextFactory>();
/// etc...
}
This sample does not work for both v2.12 and v3
2 things I noticed that need to be fixed
I'm using DryIoc in a Xamarin app, with Prism as the Mvvm framework.
I recently updated Prism, which caused my DryIoc version to update from 2.x to 3.0.
In 2.x I was using a generic method to register types for specific services:
public static void Register<TService, TImplementation, TFactory>
(
this IContainerRegistry This,
object metadataKey
) where TImplementation : TService
{
This.GetContainer()
.Register<TService, TImplementation>(
setup: Setup.With(
metadataKey,
(RequestInfo r) => r.Parent.ServiceType.IsAssignableTo<TFactory>()));
}
And I was able to resolve this using:
TFactory
(
IEnumerable<Tuple<Func<TService>, metadataType>> serviceFactories
){ }
In 3.0 this fails, in the constructor the enumerable is empty. The goal is to register keyed Service implementations, and resolve them as an enumerable in a specific parent. How should I update this for 3.0?
In 3.0, registration in the generic has changed slightly due to the removal of the RequestInfo class, and uses Request instead.
TFactory is also registered with the container.
Then, I have a registration:
containerRegistry.GetContainer().Register<TService>(
setup: Setup.With(
condition: r => !r.Parent.ServiceType.IsAssignableTo(typeof(TFactory))),
made: Made.Of(
r => ServiceInfo.Of<TFactory>(),
f => f.Create(Arg.Of<metadataType>())));
Which I use elsewhere through a constructor injected parameter as:
ctor ( Func<metadataType, TService> )
Was trying to register a service, for which there will be many concrete types, and add a decorator for one specific of them.
I tried the following code (this is LINQPad code, which is there are Dump calls in there):
void Main()
{
var container = new Container();
container.Register<IService, Service1>(serviceKey: "1");
container.Register<IService, Service2>(serviceKey: "2");
container.Register<IService, Decorator>(setup: Setup.Decorator, serviceKey: "1");
$"Main.Before".Dump();
foreach (var srv in container.Resolve<IEnumerable<IService>>())
srv.Test();
$"Main.After".Dump();
}
public interface IService
{
void Test();
}
public class Service1 : IService
{
public void Test() => $"Service1.Test()".Dump();
}
public class Service2 : IService
{
public void Test() => $"Service2.Test()".Dump();
}
public class Decorator : IService
{
private readonly IService _Service;
public Decorator(IService service) => _Service = service;
public void Test()
{
$"Decorator.Test()".Dump();
_Service.Test();
}
}
This throws this exception:
Registering Decorator 1 with not-null service key does not make sense,because decorator may be applied to multiple service of any key.If you wanted to apply decorator to services of specific key please use
setup: Setup.DecoratorOf(serviceKey: blah)
This advice does not work. First and foremost, there is no overload of ```Setup.DecoratorOf```` that has a serviceKey
parameter. Instead there is an overload with `decorateeServiceKey`, but replacing it with that doesn't work either as then it doesn't decorate anything.
Instead I had to follow the advice from here which gave me this code, that worked:
container.Register<IService, Decorator>(setup: Setup.DecoratorWith(req => req.ServiceKey == "1"));
It would be nice if the exception gave the right advice (or that the overload be added or made to work, whichever is the case here)
Currently Scope
has 2 containers: one for all stored items and another one for disposal.
For some services we know their implementation type, and know that it is not dusposable. We may put them into 1st collection, then put the rest possibly disposable to the 2nd collection.
Currently it is
rs.Scope.GetOrAdd(id, () => new Controller(...))
.
The expression contains nested lambda and therefore adds an additional compilation and invocation time.
But it is probably safe (considering that it is the a single root) to do:
rs.Scope.SetAndGet(id, new Controller(...));
Btw it may further optimized by replacing nested scoped dependencies with rs.Scope.SetAndGet
, if they are single and not Lazy (in Func, Lazy).
Moreover if variable binding is supported (dropping .NET 3.5), we may save the result if SetAndGet
to variable and use this var in graph.
Currently, the service even being a lazy resolved / injected, should be registered.
It should enable more lazy scenarios. Given that it is a default Autofac behavior, the rule will provide an easier migration.
Btw, may be the rule should work more generally for any asResolutionCall
dependencies?
... and setting without Request copying - faster and takes less GC.
To support scenarios like CreateFacade(key)
.
Say we do a web request. Its goal is create a single controller to handle request (put middlewares aside). Then scope is just a secondary thing to support a controller lifestyle.
I am trying to update to the latest preview version (3.1.0-preview-06) but there is an exception when trying to Resolve
, the exception is "Operation is not supported on this platform exception" with System.Reflection.Emit on iOS, Resolve
works tho on version 3.0.2
Thanks..
In a certain situation we have observed a memory leak in ResolveMany where KeyedFactoryDelegateCache gets filled up with "identical" values.
We have something like the following where we iterate over requestType and it's parent types and have previously registered a singleton for IIncomingRequestInterceptor<RequestTypeBase>:
var interceptorType = typeof(IIncomingRequestInterceptor<>).MakeGenericType(requestType);
var interceptors = container.ResolveMany(interceptorType).ToList();
The above line of code will add an item to the KeyedFactoryDelegateCache for each call to ResolveMany.
var interceptors = container.ResolveMany(interceptorType, ResolveManyBehavior.AsFixedArray).ToList();`
This line of code will only add an item to the KeyedFactoryDelegateCache for each unique interceptorType.
If we assume that there will be only one item (which is not true in the real use case) and use Resolve we get an item in DefaultFactoryDelegateCache for each unique interceptorType (with something registered for it).
I don't quite know how to make a useful test for this since those caches are deeper in the implementation and the actual return values from ResolveMany are just fine.
Hello,
I am trying to use the RegisterMany function restricting to the following two interfaces (MediatR):
INotificationHandler<>
IRequestHandler<,>
container.RegisterMany(new[]
{
typeof(VehicleDenormalizer).GetAssembly(),
}, Registrator.Interfaces);
How could I use the RegisterMany
to only register the two interfaces?
Thanks!
Scoped service in DryIoc is created via nested lambda Scope.GetOrAdd(id, () => new ScopedX())
;
Then inside GetOrAdd
there is a lock
held to ensure that () => new ScopedX()
is called only once.
That guarantee ensures the service is created once.
Now, let's imagine the case when it may save us:
class Y {
public Y(Lazy<ScopedX> x, Z z) { XY = x; }
}
class Z {
public Z(Lazy<ScopedX> x) { XZ = x; }
}
Now we have a concurrent logic which may access XZ.Value
and XY.Value
in parallel. In this case, without a lock
and lambda
, there is a chance to create ScopeX
multiple times.
BUT I would presume, that the case is rare and may be known before-hand.
Another option would be that creating a ScopeX
multiple time is fine, we need just ensure that we select the same instance to be used further, and another instance is dropped (e.g. first created instance wins).
So we may provide an option to simplify an expression by removing the nested lambda and creating service as Scope.GetOrTrySet(id, new ScopedX())
. This option will greatly simplify expression compilation and call stack as well.
Following will do:
var c = new Container(rules => rules.WithSmallerExpressionButNoSingleScopedInstanceCreationGuarantee());
Hi,
I'm not sure if this is a issue or by design.
I am trying to create a ViewModel-factory
public class ViewModelFactory
{
private readonly IResolver _resolver;
public ViewModelFactory(IResolver resolver)
{
_resolver = resolver;
}
public T CreateViewModel<T>(params object[] args)
{
return (T)_resolver.Resolve(typeof(T), args);
}
}
On the first call to CreateViewModel with a System.Guid as parameter
var editViewModel = _viewModelFactory.CreateViewModel<IEditViewModel>(guidId);
everything works as expected. The constructor of the registered EditViewModel is run with the provided guidId, and other parameters injected. However on a second call
var editViewModel = _viewModelFactory.CreateViewModel<IEditViewModel>(anotherGuidId);
the guid-value from the first call is injected to the constructor again.
It seems to me that DryIoc's Resolve caches object[] args values.
Is this intended?
I'm aware that I can use
var getter = _resolver.Resolve<Func<Guid,T>>();
getter(guidId)
but not all of my viewmodels require a guid as parameter. Some require no guid, some require two, and some might require other values only known at runtime.
Thanks for any advice
System.MissingMethodException: Method not found: 'DryIoc.Setup DryIoc.Setup.With(System.Object, System.Func2<DryIoc.Request,Boolean>, Boolean, Boolean, Boolean, Boolean, Boolean, Boolean, Boolean, Boolean, Int32)'. at at DryIoc.Microsoft.DependencyInjection.DryIocAdapter.WithDependencyInjectionAdapter(IContainer container, IEnumerable
1 descriptors, Func3 registerDescriptor, Func
2 throwIfUnresolved)
I am using:
DryIoc.Microsoft.DependencyInjection 2.2.0-preview-01
DryIoc.dll 3.1.0-preview-05
Actually it is my fail to not include this change into v3.0.
The change is in internal but still may be breaking for someone. Comparing to the previous behavior, the change is more permissive (some nested dependencies allowed to be not registered yet) - so now it won't fail where previously it would.
But lets consider this a fix, bringing less surprizes to users. Then making it into 3.1 is fine :)
To enable factory delegate compilation for selected services, without actually creating them.
We may use GenerateResolutionExpressions(roots)
followed by compilation.
It won't require a complex logic for registry swapping, it may effectively happen while scope creation (which is usually a single threaded).
Since using a composition root seems to be easier with IRegistrator
than with IContainer
(a nested container is injected?), it would be nice if there was parity between the methods available on the two interfaces so that IRegistrator
could be used instead of IContainer
.
For instance, these methods are available on/for IContainer
but not IRegistrator
:
I didn't check if overloads are missing.
We figured out, that we can speed up the executionen of an short living application (like a console application) with Expression<TDelegate>.Compile(preferInterpretation: true)
, because of avoiding some JIT overhead.
Can you maybe add a rule to DryIoc, so we can switch between preferInterpretation: true and preferInterpretation: false for the compilation of the resolve trees?
Idea is to get rid off nested lambdas for the scoped reuse dependencies. The object graph is created sequentally in depth left order traversal, so we can create a first dependency (in order) and use Scope.Get(id)
for the subsequent objects.
Currently, error includes candidates for leaf level only. We may provide more context.
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.