- Notifications
You must be signed in to change notification settings - Fork1
usausa/Smart-Net-Resolver
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Smart.Resolver .NET is simplified resolver library, degradation version of Ninject.
- ASP.NET Core / Generic Host support
- Transient, Singleton, Container(child) and custom scope supported
- Callback, Constant provider supported
- Property injection supported (optional)
- Custom initialize processor supported
- Construct with parameter supported
- Constraint supported (like keyed)
- Missing handler supported (For automatic registration, open generic type, ...)
- Customization-first implementation, but not too late (see benchmark)
publicinterfaceIService{}publicsealedclassService:IService{}publicsealedclassController{privateIServiceService{get;}publicController(IServiceservice){Service=service;}}// Usagevarconfig=newResolverConfig();config.Bind<IService>().To<Service>().InSingletonScope();config.Bind<Controller>().ToSelf();varresolver=config.ToResolver();varcontroller=resolver.Get<Controller>();
| Package | Note |
|---|---|
| Core libyrary | |
| Microsoft.Extensions.DependencyInjection integration | |
| Configuration extension |
Supported binding syntax.
- Bind
- To
// Type IService to Service Type instanceconfig.Bind<IService>().To<Service>();
- ToSelf
// Type Controller to Controller Type instanceconfig.Bind<Controller>().ToSelf();
- ToMethod
// Type IScheduler to factory methodconfig.Bind<IScheduler>().ToMethod(x=>x.Get<ISchedulerFactory>().GetScheduler());
- ToConstant
// Type Messenger to instanceconfig.Bind<Messenger>().ToConstant(Messenger.Default);
- InTransientScope
- InSingletonScope
- InScope
- Keyed
- WithConstructorArgument
- WithPropertyValue
- WithMetadata
Supported scope.
- New instance created each time
- Lifecycle is not managed by resolver
config.Bind<TransientObject>().ToSelf().InTransientScope();
or
config.Bind<TransientObject>().ToSelf();
- Single instance created and same instance returned
- Lifecycle managed by resolver (IScopeStorage) and Dispose called when resolver disposed
config.Bind<SingletonObject>().ToSelf().InSingletonScope();
- Single instance created and same instance returned per child container
- Lifecycle managed by child container and Dispose called when resolver disposed
config.Bind<ScopeObject>().ToSelf().InContainerScope();
- You can create a custom scope
config.Bind<CustomeScopeObject>().ToSelf().InScope(newCustomeScope());
Prepared by standard.
Key constraint for lookup binding.
publicsealedclassChild{}publicsealedclassParent{pulbicChild Child{get;}publicParent([ResolveBy("foo")]Childchild){Child=child;}}// Usagevarconfig=newResolverConfig();config.Bind<Child>().ToSelf().InSingletonScope().Keyed("foo");config.Bind<Child>().ToSelf().InSingletonScope().Keyed("bar");config.Bind<Parent>().ToSelf();varresolver=config.ToResolver();varparent=resolver.Get<Parent>();varfoo=resolver.Get<Child>("foo");varbar=resolver.Get<Child>("bar");Debug.Assert(parent.Child==foo);Debug.Assert(parent.Child!=bar);
Mark of property injection target or select constructor.
publicsealedclassHasPropertyObject{[Inject]publicTargetTarget{get;set;}}
Set constructor argument or property value.
publicsealedclassSceduler{publicSceduler(ITimertimer,inttimeout){}}// Usageconfig.Bind<ITimer>().To<Timer>().InSingletonScope();config.Bind<Sceduler>().ToSelf().InSingletonScope().WithConstructorArgument("timeout",30);
StandardResolver is constructed from sub-components. Change the sub-components in ResolverConfig, can be customized StandardResolver.
// Add custom processor to pipelinepublicsealedclassCustomInitializeProcessor:IProcessor{publicvoidInitialize(objectinstance){...}}config.UseProcessor<CustomInitializeProcessor>();
// Add custome scopepublicsealedclassCustomScope:IScope{privatestaticreadonlyThreadLocal<Dictionary<IBinding,object>>Cache=newThreadLocal<Dictionary<IBinding,object>>(()=>newDictionary<IBinding,object>());publicIScopeCopy(IComponentContainercomponents){returnthis;}publicFunc<IResolver,object>Create(IBindingbinding,Func<object>factory){return resolver=>{if(Cache.Value.TryGetValue(binding,outvarvalue)){returnvalue;}value=factory();Cache.Value[binding]=value;returnvalue;};}}config.Components.Add<CustomScopeStorage>();config.Bind<SimpleObject>().ToSelf().InScope(newCustomScope());
See the sample project for details.
publicstaticclassProgram{publicstaticvoidMain(string[]args){CreateHostBuilder(args).Build().Run();}publicstaticIHostBuilderCreateHostBuilder(string[]args)=>Host.CreateDefaultBuilder(args).UseServiceProviderFactory(newSmartServiceProviderFactory()).ConfigureWebHostDefaults(webBuilder=>{webBuilder.UseStartup<Startup>();});}
publicsealedclassStartup{...publicvoidConfigureServices(IServiceCollectionservices){services.AddMvc();}publicvoidConfigureContainer(ResolverConfigconfig){// Add component}...}
publicstaticclassProgram{publicstaticasyncTaskMain(string[]args){awaitnewHostBuilder().UseServiceProviderFactory(newSmartServiceProviderFactory()).ConfigureContainer<ResolverConfig>(ConfigureContainer).RunAsync();}privatestaticvoidConfigureContainer(ResolverConfigconfig){// Add component}}
Ohter topics.
If the class implements Initializable, Initialized called after construct.
protectedclassInitializableObject:IInitializable{publicboolInitialized{get;privateset;}publicvoidInitialize(){Initialized=true;}}// Usageconfig.Bind<InitializableObject>().ToSelf().InSingletonScope();varobj=resolver.Get<InitializableObject>();Debug.Assert(obj.Initialized);
If custom constraints want is as follows:
// Create IConstraint implementpublicsealedclassHasMetadataConstraint:IConstraint{publicstringKey{get;}publicHasMetadataConstraint(stringkey){Key=key;}publicboolMatch(IBindingMetadatametadata){returnmetadata.Has(Key);}}// Create ConstraintAttribute derived classpublicsealedclassHasMetadataAttribute:ConstraintAttribute{publicstringKey{get;}publicHasMetadataAttribute(stringkey){Key=key;}publicoverrideIConstraintCreateConstraint(){returnnewHasMetadataConstraint(Key);}}// UsagepublicsealedclassParent{pulbicChild Child{get;}publicParent([HasMetadata("hoge")]Childchild){Child=child;}}config.Bind<Child>().ToSelf().InSingletonScope();config.Bind<Child>().ToSelf().InSingletonScope().WithMetadata("hoge",null);config.Bind<Parent>().ToSelf();
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3958/23H2/2023Update/SunValley3)AMD Ryzen 9 5900X, 1 CPU, 24 logical and 12 physical cores.NET SDK 8.0.400 [Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2 MediumRun : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2Job=MediumRun Jit=RyuJit Platform=X64 Runtime=.NET 8.0 IterationCount=15 LaunchCount=2 WarmupCount=10| Method | Mean | Error | StdDev | Min | Max | P90 | Gen0 | Allocated |
|---|---|---|---|---|---|---|---|---|
| Singleton | 2.258 ns | 0.0221 ns | 0.0331 ns | 2.223 ns | 2.328 ns | 2.313 ns | - | - |
| Transient | 11.712 ns | 0.8301 ns | 1.2424 ns | 10.154 ns | 13.742 ns | 13.439 ns | 0.0014 | 24 B |
| Combined | 22.017 ns | 0.2220 ns | 0.3322 ns | 21.503 ns | 22.911 ns | 22.385 ns | 0.0014 | 24 B |
| Complex | 36.063 ns | 0.5290 ns | 0.7754 ns | 35.258 ns | 38.750 ns | 36.957 ns | 0.0081 | 136 B |
| Generics | 4.113 ns | 0.0513 ns | 0.0720 ns | 3.995 ns | 4.249 ns | 4.194 ns | 0.0014 | 24 B |
| MultipleSingleton | 2.074 ns | 0.0226 ns | 0.0324 ns | 2.033 ns | 2.143 ns | 2.116 ns | - | - |
| MultipleTransient | 91.725 ns | 0.8332 ns | 1.2471 ns | 89.852 ns | 94.266 ns | 93.480 ns | 0.0110 | 184 B |
| AspNet | 101.012 ns | 0.8376 ns | 1.1465 ns | 99.009 ns | 103.599 ns | 102.215 ns | 0.0153 | 256 B |
- AOP( ゚д゚)、ペッ
- Method Injection (I don't need but it is possible to cope)
- Circular reference detection (Your design bug)
About
Dependency resolver.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
No packages published
Uh oh!
There was an error while loading.Please reload this page.