Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active February 23, 2022 07:11
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
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
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