Skip to content

C# Dependency-Injection library supports attributes, assembly scanning, factory methods and many others... πŸ˜‹πŸ˜Ž

License

Notifications You must be signed in to change notification settings

kacperfaber/Spencer.NET

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Spencer.NET

Open Source project of smart IoC Container made by programmer for programmer.
Is made with a view to creating class libraries.

Author

Kacper Faber, Poland


Requires

  • NET STANDARD 2.0
    or newest

  • .NET CORE 2.0
    or newest

  • .NET FRAMEWORK 4.61
    or newest


Versions

  • 1.0 (29.04.2020)
  • 1.0.1 (30.04.2020)
  • 1.0.2 (26.05.2020)
  • 1.0.2.1 (26.05.2020)
  • 1.0.2.2 (27.05.2020)
  • 1.0.5 (12.06.2020)
  • 1.0.6 (13.06.2020)
  • 1.0.75 (16.06.2020)
  • 1.2 (24.07.2023)

Warnings

Please, ensure your interfaces have reachable implementations.
If they will not, program will throw System.NullReferenceException.
I'm working for fix this issue.

Changelog [1.2]

NamespaceInterfaceValidator class accepts null '@interface', then returns null.


Usage


Installing package

Spencer.NET is available on nuget.org.
You can use one of follow commands.

dotnet add package Spencer.NET

Install-Package Spencer.NET


Adding using

Spencer.NET using one statement for every feature.
It is it.

using Spencer.NET;


Create Container

Constructors of both of containers are too long to
writing it by contributor programmer.
You can use tested and safely ContainerFactory class

IContainer container = ContainerFactory.Container();


Create ReadOnlyContainer

Constructors of both of containers are too long to
writing it by contributor programmer.
You can use tested and safely ContainerFactory class

This container cannot be updated in him lifetime

You should provide instance of Storage class

Prefered way is using StorageBuilder


IReadOnlyContainer container = ContainerFactory.ReadOnlyContainer(storage);


Create Storage

ReadOnlyContainer cannot be updated in him lifetime.
To provides static registrations, you have to use instance of Storage class
Prefered way is using StorageBuilder class.

StorageBuilder.Build():IStorage
Returns Storage instance

StorageBuilder.Register<T>():StorageBuilder
Registering generic T as class or interface

StorageBuilder.Register(Type):StorageBuilder
Registering class or interface

StorageBuilder.Register<T>(params object[]):StorageBuilder (issue fixed in v1.0.2-1)
Registering generic T as class or interface with
given parameters to constructor
with compatible parameters

StorageBuilder.Register(Type, params object[]):StorageBuilder (issue fixed in v1.0.2-1)
Registering class or interface using constructor
with compatible parameters

StorageBuilder.RegisterObject(object):StorageBuilder
Registering class with instance gived in parameter.
Registration type will be taken from unboxed instance.

StorageBuilder.RegisterObject<T>(T):StorageBuilder
Registering class with instance of gived in parameter.
Registration type will be taken from T.

StorageBuilder.RegisterAssembly(Assembly):StorageBuilder
Registering assembly types.

StorageBuilder.RegisterAssembly(AssemblyName):StorageBuilder
Registering assembly types

StorageBuilder.RegisterAssemblies(params Assembly[]):StorageBuilder
Registering assembly types

StorageBuilder.RegisterAssemblies(params AssemblyName[]):StorageBuilder
Registering assembly types


Attributes

  • SingleInstance service will using single instance of class

  • MultiInstance service will create a new instance for each trying to get

  • AutoValue service will be instantiate on registering process

  • Exclude (Type) excluding type from registration.

  • ServiceConstructor pointing to default constructor for class, if any constructor will be find automatically

  • Factory pointing to static method, which will be used to instantiate new instance of a class

  • Factory (Type) pointing to static method, which will be used to instantiate new instance of a class. Using Type argument to set real return type e.g factory returns System.String as System.Object

  • [Obsolete] FactoryResult (Type) expanding factory method for good type which actually is producing in this method. Is Obsolete, instead use FactoryAttribute (Type)



Troubleshooting

[SingleInstance]
[MultiInstance]
class Test
{
}

// Test will be registered as SingleInstance.
class Test
{
}

// Test will be registered as SingleInstance
// SingleInstance is default
class Test
{
}

// Test will be registered as not AutoValue,
// Class will be instantiate, on first trying to get
[MultiInstance]
class Test
{
}

Test instance = new Test();
IContainer container = ContainerFactory.Container();
container.RegisterObject(instance);

// Test will be registered as MultiInstace
// Given instance will be ever returns using Resolve methods.
class Test
{
    [Factory]
    public static Test FactoryMethod() => new Test();

    [ServiceConstructor]
    public Test()
    {
    }
}

// Factory always be checked first.
// In this situation Test will be instantiate using factory

Parametrized Constructors

Mechanism for finding constructor always will be picking accessible and
with the smallest count of parameters he have, or he could have.
You would use ServiceConstructor attribute?
If you want dynamically choose constructor you would to use,
i'm providing functionality to find constructor by given parameters.
Lets see the sample... :>

class Test
{
    // #1
    public Test(int x) {}
    
    // #2
    public Test(int x, int y) {}

    // #3 
    public Test(string str, bool b) {}
}

// Container.Register<Test>(0);
// Will invoke #1 constructor
// params
// x = 0

// Container.Register<Test>(1, 2);
// Will use #2 constructor
// params
// x = 1,
// y = 2

// Container.Register<Test>(true, "Hello World!");
// Will use #3 constructor
// params 
// str = "Hello World!"
// b = true

Factories

Factories is a static methods generating instance of a class.

They can returns interface, if they will have a FactoryResult(Type) attribute,


> which will be pointing to the valid returns type.

They can take dependencies as their parameters

Version 1.1 provides factories as Public Methods

class Test 
{
    Test() {}
        
    [Factory]
    public static Test FactoryMethod() => new Test();
}
interface ITest 
{
}

class Test : ITest
{
    Test() {}
       
    // Use it instead FactoryResult
    [Factory(typeof(Test))]
    public static ITest FactoryMethod() => new Test();
}
class TestManager
{
    public Test CreateInstance() => new Test();
}

class Test
{
    [Factory]
    public static Test MakeTest(TestManager testManager)
    {
        return testManager.CreateInstance();
    }
}

// Parameters are in
// Version 1.0.75

Injections

Spencer.NET want to help you. If you want, you cannot inject everything in constructor.
I am providing attributes Inject, TryInject and Auto.

Inject way is not recommended for good Dependency Injection


  • Injections

    • Inject trying to resolve instance from self Container,

    if could not found any matching will throw `ResolveException`
    • TryInject trying to resolve instance from self Container,

    if could not found any matching set variable to `null`
  • Auto initializing simple types

class OldWay
{
    public IEnumerable<int> Ints { get; set; }
    public IDep Dep { get; set; }
    
    public OldWay(IDep dep)
    {
        Dep = dep;
        Ints = new List<int>();
    }
}

class NewWay
{
    [Auto]
    public IEnumerable<int> Ints { get; set; }

    [Inject]
    public IDep Dep { get; set; } 
}

About

C# Dependency-Injection library supports attributes, assembly scanning, factory methods and many others... πŸ˜‹πŸ˜Ž

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages