Skip to content

Commit

Permalink
Resolved #11: Change design of the resolving progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
hikalkan committed Apr 8, 2017
1 parent 6c5521b commit 3d32519
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@
{
public class MyTestClass3 : BaseTestClass
{
public MyTestClass3()
{

}

public override void Dispose()
{
base.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Castle.Core;
using Castle.MicroKernel.Registration;
using Castle.Windsor.Installer;
using Castle.Windsor.MsDependencyInjection.Tests.TestClasses;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Specification;
using Microsoft.Extensions.DependencyInjection.Specification.Fakes;
using Shouldly;
using Xunit;

Expand All @@ -18,7 +17,7 @@ public class WindsorSpecificationTests : DependencyInjectionSpecificationTests,

protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection)
{
var windsorContainer = new MsCompatibleWindsorContainer();
var windsorContainer = new WindsorContainer();

windsorContainer.Register(Component.For<DisposeCounter>().LifestyleSingleton());

Expand Down Expand Up @@ -207,9 +206,9 @@ public void Windsor_Dispose_Test_With_Interceptor()
var windsorContainer = new WindsorContainer();
windsorContainer.Register(
Component.For<DisposeCounter>().LifestyleSingleton(),
Component.For<MyTestInterceptor>().LifestyleCustom<MsScopedTransientLifestyleManager>(),//.LifestyleTransient(),
Component.For<MyTestClass2>().LifestyleCustom<MsScopedTransientLifestyleManager>(),//.LifestyleTransient(),
Component.For<MyTestClass3>().LifestyleCustom<MsScopedTransientLifestyleManager>()//.Interceptors<MyTestInterceptor>().LifestyleTransient()
Component.For<MyTestInterceptor>().LifestyleTransient(),
Component.For<MyTestClass2>().LifestyleTransient(),
Component.For<MyTestClass3>().Interceptors<MyTestInterceptor>().LifestyleTransient()
);

var obj = windsorContainer.Resolve<MyTestClass2>();
Expand All @@ -221,7 +220,7 @@ public void Should_Resolve_Registered_Enumerable()
{
var collection = new ServiceCollection();

collection.AddSingleton((IEnumerable<MyTestClass3>) new List<MyTestClass3>
collection.AddSingleton((IEnumerable<MyTestClass3>)new List<MyTestClass3>
{
new MyTestClass3(),
new MyTestClass3(),
Expand Down Expand Up @@ -252,12 +251,95 @@ public void Resolving_Scoped_Test()

var serviceProvider = CreateServiceProvider(collection);

var obj1 = serviceProvider.GetService<MyTestClass3>();
var obj2 = serviceProvider.GetService<MyTestClass3>();
using (var scope = serviceProvider.CreateScope())
{
var obj1 = scope.ServiceProvider.GetService<MyTestClass3>();
var obj2 = scope.ServiceProvider.GetService<MyTestClass3>();
obj1.ShouldBeSameAs(obj2);
}
}

obj1.ShouldBeSameAs(obj2);
[Fact]
public void Resolving_Scoped_From_Container_Test()
{
var collection = new ServiceCollection();

collection.AddScoped<MyTestClass3>();

var serviceProvider = CreateServiceProvider(collection);
var windsorContainer = serviceProvider.GetService<IWindsorContainer>();

var obj1 = windsorContainer.Resolve<MyTestClass3>();
var obj2 = windsorContainer.Resolve<MyTestClass3>();
obj1.ShouldNotBeSameAs(obj2);
}

[Fact]
public void FactoryServicesAreCreatedAsPartOfCreatingObjectGraph_2()
{
var services = new ServiceCollection();
services.AddTransient<IFakeService, FakeService>();
services.AddTransient<IFactoryService>((Func<IServiceProvider, IFactoryService>)(p =>
{
IFakeService service = p.GetService<IFakeService>();
return (IFactoryService)new TransientFactoryService()
{
FakeService = service,
Value = 42
};
}));
services.AddScoped<ScopedFactoryService>((Func<IServiceProvider, ScopedFactoryService>)(p =>
{
IFakeService service = p.GetService<IFakeService>();
return new ScopedFactoryService()
{
FakeService = service
};
}));
services.AddTransient<ServiceAcceptingFactoryService>();
IServiceProvider serviceProvider = this.CreateServiceProvider((IServiceCollection)services);
using (var scope = serviceProvider.CreateScope())
{
serviceProvider = scope.ServiceProvider;

ServiceAcceptingFactoryService service1 = serviceProvider.GetService<ServiceAcceptingFactoryService>();
ServiceAcceptingFactoryService service2 = serviceProvider.GetService<ServiceAcceptingFactoryService>();
Assert.Equal<int>(42, service1.TransientService.Value);
Assert.NotNull((object)service1.TransientService.FakeService);
Assert.Equal<int>(42, service2.TransientService.Value);
Assert.NotNull((object)service2.TransientService.FakeService);
Assert.NotNull((object)service1.ScopedService.FakeService);
Assert.NotSame((object)service1.TransientService, (object)service2.TransientService);
Assert.Same((object)service1.ScopedService, (object)service2.ScopedService);
}
}

[Fact]
public void ShouldReleaseScopedOnScopeDisposeButNotBefore()
{
var collection = new ServiceCollection();

collection.AddScoped<MyTestClass3>();

var serviceProvider = CreateServiceProvider(collection);
var windsorContainer = serviceProvider.GetService<IWindsorContainer>();

MyTestClass3 obj;

using (var scope = serviceProvider.CreateScope())
{
obj = scope.ServiceProvider.GetService<MyTestClass3>();
obj.IsDisposed.ShouldBeFalse();

windsorContainer.Release(obj);
obj.IsDisposed.ShouldBeFalse();
}

obj.IsDisposed.ShouldBeTrue();
}

//TODO: TEST - Globally resolved objects should be disposed when the container is disposed?

public void Dispose()
{
Assert.Null(MsLifetimeScope.Current);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>2.0.0-preview2</Version>
<Version>2.0.0-preview3</Version>
<TargetFrameworks>net452;net46;netstandard1.5</TargetFrameworks>
<AssemblyName>Castle.Windsor.MsDependencyInjection</AssemblyName>
<PackageId>Castle.Windsor.MsDependencyInjection</PackageId>
Expand Down
10 changes: 10 additions & 0 deletions src/Castle.Windsor.MsDependencyInjection/GlobalMsLifetimeScope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Castle.Windsor.MsDependencyInjection
{
public class GlobalMsLifetimeScope : MsLifetimeScope
{
public GlobalMsLifetimeScope(IWindsorContainer container)
: base(container)
{
}
}
}

This file was deleted.

20 changes: 0 additions & 20 deletions src/Castle.Windsor.MsDependencyInjection/MsCompatibleKernel.cs

This file was deleted.

This file was deleted.

55 changes: 28 additions & 27 deletions src/Castle.Windsor.MsDependencyInjection/MsLifeTimeScope.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Castle.Core.Internal;
using Castle.MicroKernel;
using Castle.MicroKernel.Lifestyle.Scoped;

namespace Castle.Windsor.MsDependencyInjection
{
public interface IMsLifetimeScope
{
ILifetimeScope WindsorLifeTimeScope { get; }
void AddInstance(object instance);
void AddChild(MsLifetimeScope lifetimeScope);
void RemoveChild(MsLifetimeScope lifetimeScope);
void Dispose();
}

/// <summary>
/// Wrapper for Windsor lifetime infrastructure.
/// </summary>
public class MsLifetimeScope
public class MsLifetimeScope : IMsLifetimeScope
{

#if NET452
public static MsLifetimeScope Current
public static IMsLifetimeScope Current
{
get { return _current; }
set { _current = value; }
}

[ThreadStatic]
private static MsLifetimeScope _current;
private static IMsLifetimeScope _current;
#else
public static MsLifetimeScope Current
public static IMsLifetimeScope Current
{
get { return _current.Value; }
set { _current.Value = value; }
}

private static readonly AsyncLocal<MsLifetimeScope> _current = new AsyncLocal<MsLifetimeScope>();
private static readonly AsyncLocal<IMsLifetimeScope> _current = new AsyncLocal<IMsLifetimeScope>();
#endif

public ILifetimeScope WindsorLifeTimeScope { get; }

private readonly List<MsLifetimeScope> _children;

private readonly HashSet<Burden> _transientBurdens;
private readonly HashSet<object> _resolvedInstances;
private readonly IWindsorContainer _container;

private ThreadSafeFlag _disposed;

public MsLifetimeScope()
public MsLifetimeScope(IWindsorContainer container)
{
_container = container;

WindsorLifeTimeScope = new DefaultLifetimeScope();
_children = new List<MsLifetimeScope>();

_transientBurdens = new HashSet<Burden>();
_children = new List<MsLifetimeScope>();
_resolvedInstances = new HashSet<object>();
_disposed = new ThreadSafeFlag();
}

public void Track(Burden transientBurden)
public void AddInstance(object instance)
{
_transientBurdens.Add(transientBurden);
transientBurden.Releasing += TransientBurden_Releasing;
}

private void TransientBurden_Releasing(Burden burden)
{
_transientBurdens.Remove(burden);
_resolvedInstances.Add(instance);
}

public void AddChild(MsLifetimeScope lifetimeScope)
Expand Down Expand Up @@ -94,18 +98,15 @@ public void Dispose()
_children.Clear();
}

WindsorLifeTimeScope.Dispose();

foreach (var burden in _transientBurdens.Reverse().ToList())
foreach (var instance in _resolvedInstances)
{
if (_transientBurdens.Contains(burden))
{
burden.Release();
}
_container.Release(instance);
}

WindsorLifeTimeScope.Dispose();
}

public static IDisposable Using(MsLifetimeScope newLifetimeScope)
public static IDisposable Using(IMsLifetimeScope newLifetimeScope)
{
var previous = Current;
Current = newLifetimeScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ namespace Castle.Windsor.MsDependencyInjection
/// </summary>
public class MsLifetimeScopeProvider
{
public MsLifetimeScope LifetimeScope { get; }
public IMsLifetimeScope LifetimeScope { get; }

public MsLifetimeScopeProvider(GlobalMsLifetimeScopeProvider globalMsLifetimeScopeProvider)
public MsLifetimeScopeProvider()
{
LifetimeScope = MsLifetimeScope.Current ??
globalMsLifetimeScopeProvider.LifetimeScope;
LifetimeScope = MsLifetimeScope.Current;
}
}
}

This file was deleted.

Loading

0 comments on commit 3d32519

Please sign in to comment.