Closed mcdis closed 5 years ago
Hi @mcdis
I’ll see if I can find a test that shows something like this. Ultimately what I think you want to do is use the ‘UsingLifestyle’ method.
It takes a ‘Func<Type,ICompiledLifestyle>’ that will let you pick lifestyle based on the type being exported. Here you can put your logic to decide what should or shouldn’t be a singleton
Can you show example of using UsingLifestyle
?
@mcdis I added a test showing how to use UsingLifestyle but I also remembered you could also use an IActivationStrategyInspector that would act on all exports.
public class StrategyInspector : IActivationStrategyInspector
{
public void Inspect<T>(T strategy) where T : class, IActivationStrategy
{
if (strategy is ICompiledExportStrategy exportStrategy)
{
if (exportStrategy.ActivationType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IFoo)))
{
exportStrategy.Lifestyle = new SingletonLifestyle();
}
}
}
}
Thank you! Can I control lifetime strategy for not exported types? example:
interface IFoo{}
class AFoo:IFoo {}
class BFoo:IFoo {}
class ConsumerCache
{
public ConsumerCache(AFoo _a)
{
A = _a;
}
public AFoo A {get;}
}
class Consumer
{
public Consumer(AFoo _a,BFoo _b,ConsumerCache _cache)
{
_cache.A == _a; // true, singletone
}
}
var scope = new DependencyInjectionContainer();
scope.Locate<Consumer>();
So, I've got module like system and need to resolve some processors but I want to skip export phase because I know that every resolvable type which implement IFoo must to be singletone. Looks like I've to add some custom strategy...
In my case IFoo implementators can locate in different assemblies and from case to case I can use different set and I don't want to have export registration phase.
PS: StrategyInspector works only for explicit exported types.
I’ll take a look later today as the inspectors should be run against all exports even non explicitly exported types.
@mcdis I've added a new unit test here to show that interceptors are run against non exported types.
Can you provide an example app where it's not working?
interface IFoo { }
class FooInspector : IActivationStrategyInspector
{
public void Inspect<T>(T _strategy) where T : class, IActivationStrategy
{
if (_strategy is ICompiledExportStrategy exportStrategy)
{
if (exportStrategy.ActivationType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IFoo)))
exportStrategy.Lifestyle = new SingletonLifestyle();
}
}
}
class AFoo : IFoo { }
class Test
{
public Test(AFoo _foo) => A = _foo;
public AFoo A { get; }
}
class Program
{
static void Main()
{
var scope = new DependencyInjectionContainer();
var child = scope.CreateChildScope(_ => _.AddInspector(new FooInspector()));
var test = child.Locate<Test>();
var a = child.Locate<AFoo>();
var equals = test.A == a; // Fail
}
}
Works only with inspector in root scope. Doesn't work when use nested scopes
@mcdis the reason for that is that missing strategies are registered in the root container not the child container where you’ve installed an inspector. While it doesn’t work the way you’d like it to it’s working correctly.
Can I intercept missing types and do registration on the child scope level?
@mcdis by default there is just one ConcreteExportStrategyProvider
in the root container. You could add one in the child scope like so
scope.CreateChildScope(_ =>
{
_.AddInspector(new FooInspector());
_.AddMissingExportStrategyProvider(new ConcreteExportStrategyProvider()));
}
@ipjohnson holy interface, that's works! AddMissingExportStrategyProvider + Inspector, yeah!
Hi Ian, thank you for your job! I need to autoregister types as singletone that implement some interface
IFoo
but I don't know exact types. for example if the class to activate depends onCustomFoo : IFoo
thanCustomFoo
have to be resolved as singletone