Last active
February 23, 2022 07:11
-
-
Save akimboyko/4622557 to your computer and use it in GitHub Desktop.
Custom scope for Ninject that returns same instance based on first constructor argument. Using both kernel and factory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
using(var kernel = new StandardKernel(new Module())) | |
{ | |
kernel.Load<FuncModule>(); // for sake of LinqPAD | |
var instance1 = kernel.Get<MyClass>(new ConstructorArgument("myArg", "test")); | |
var instance2 = kernel.Get<MyClass>(new ConstructorArgument("myArg", "test")); | |
Assert.That(instance1, Is.Not.Null.And.SameAs(instance2)); | |
var instance3 = kernel.Get<MyClass>(new ConstructorArgument("myArg", "rest")); | |
Assert.That(instance3, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance3, Is.Not.Null.And.Not.SameAs(instance2).And.Not.EqualTo(instance2)); | |
var instance4 = kernel.Get<MyClass>(new ConstructorArgument("myArg", "best")); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance3).And.Not.EqualTo(instance3)); | |
var factory = kernel.Get<IMyClassFactory>(); | |
instance1 = factory.Create("test"); | |
instance2 = factory.Create("test"); | |
Assert.That(instance1, Is.Not.Null.And.SameAs(instance2)); | |
instance3 = factory.Create("rest"); | |
Assert.That(instance3, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance3, Is.Not.Null.And.Not.SameAs(instance2).And.Not.EqualTo(instance2)); | |
instance4 = factory.Create("best"); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance1).And.Not.EqualTo(instance1)); | |
Assert.That(instance4, Is.Not.Null.And.Not.SameAs(instance3).And.Not.EqualTo(instance3)); | |
} | |
} | |
public class MyClass | |
{ | |
public string MyArg { get; private set; } | |
public MyClass(string myArg) | |
{ | |
MyArg = myArg; | |
} | |
public override bool Equals(object other) | |
{ | |
if(other == null | |
|| other.GetType() != typeof(MyClass)) | |
{ | |
return false; | |
} | |
return MyArg == ((MyClass)other).MyArg; | |
} | |
public override int GetHashCode() | |
{ | |
return (MyArg ?? string.Empty).GetHashCode(); | |
} | |
} | |
public interface IMyClassFactory | |
{ | |
MyClass Create(string myArg); | |
} | |
public class Module : NinjectModule | |
{ | |
// stores string myArg to protect from CG | |
ConcurrentBag<string> ParamSet = new ConcurrentBag<string>(); | |
public override void Load() | |
{ | |
Bind<IMyClassFactory>() | |
.ToFactory(); | |
Bind<MyClass>() | |
.ToSelf() | |
// custom scope | |
.InScope((context) => | |
{ | |
// get first constructor argument | |
var param = context.Parameters.First().GetValue(context, context.Request.Target) as string; | |
// retrieves system reference to string | |
param = string.Intern(param); | |
// protect value from CG | |
if(param != null && ParamSet.Contains(param)) | |
{ | |
// protect from GC | |
ParamSet.Add(param); | |
} | |
// make Ninject to return same instance for this argument | |
return param; | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment