Updating the internal standalone context, and adding one that is limited to the core assembly to limit dependencies.

This commit is contained in:
Morten Christensen
2013-05-17 05:51:22 -02:00
parent d94772892d
commit ecfe51134d
13 changed files with 317 additions and 10 deletions

View File

@@ -42,4 +42,5 @@ using System.Security.Permissions;
[assembly: InternalsVisibleTo("Umbraco.Courier.Persistence")]
[assembly: InternalsVisibleTo("Concorde.Sync")]
[assembly: InternalsVisibleTo("Umbraco.Belle")]
[assembly: InternalsVisibleTo("Umbraco.Belle")]
[assembly: InternalsVisibleTo("Umbraco.VisualStudio")]

View File

@@ -165,7 +165,7 @@ namespace Umbraco.Core.Services
}
/// <summary>
/// Gets the <see cref="IMacroService"/>
/// Gets the <see cref="UserService"/>
/// </summary>
internal IUserService UserService
{

View File

@@ -0,0 +1,54 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
namespace Umbraco.Core.Standalone
{
internal class ServiceContextManager : IDisposable
{
private readonly string _connectionString;
private readonly string _providerName;
private ServiceContext _serviceContext;
private readonly StandaloneCoreApplication _application;
public ServiceContextManager(string connectionString, string providerName)
{
_connectionString = connectionString;
_providerName = providerName;
_application = StandaloneCoreApplication.GetApplication();
_application.Start();
}
public ServiceContext Services
{
get
{
if (_serviceContext == null)
{
var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName);
var dbContext = new DatabaseContext(dbFactory);
Database.Mapper = new PetaPocoMapper();
_serviceContext = new ServiceContext(
new PetaPocoUnitOfWorkProvider(dbFactory),
new FileUnitOfWorkProvider(),
new PublishingStrategy());
//initialize the DatabaseContext
dbContext.Initialize(_providerName);
}
return _serviceContext;
}
}
public void Dispose()
{
((IDisposable)ApplicationContext.Current).Dispose();
_application.Dispose();
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Standalone
{
internal class StandaloneCoreApplication : UmbracoApplicationBase
{
/// <summary>
/// Initializes a new instance of the <see cref="StandaloneCoreApplication"/> class.
/// </summary>
protected StandaloneCoreApplication() { }
/// <summary>
/// Provides the application boot manager.
/// </summary>
/// <returns>An application boot manager.</returns>
protected override IBootManager GetBootManager()
{
return new StandaloneCoreBootManager(this, _handlersToAdd, _handlersToRemove);
}
#region Application
private static StandaloneCoreApplication _application;
private static bool _started;
private static readonly object AppLock = new object();
/// <summary>
/// Gets the instance of the standalone Umbraco application.
/// </summary>
public static StandaloneCoreApplication GetApplication()
{
lock (AppLock)
{
return _application ?? (_application = new StandaloneCoreApplication());
}
}
/// <summary>
/// Starts the application.
/// </summary>
public void Start()
{
lock (AppLock)
{
if (_started)
throw new InvalidOperationException("Application has already started.");
Application_Start(this, EventArgs.Empty);
_started = true;
}
}
#endregion
#region IApplicationEventHandler management
private readonly List<Type> _handlersToAdd = new List<Type>();
private readonly List<Type> _handlersToRemove = new List<Type>();
/// <summary>
/// Associates an <see cref="IApplicationEventHandler"/> type with the application.
/// </summary>
/// <typeparam name="T">The type to associate.</typeparam>
/// <returns>The application.</returns>
/// <remarks>Types implementing <see cref="IApplicationEventHandler"/> from within
/// an executable are not automatically discovered by Umbraco and have to be
/// explicitely associated with the application using this method.</remarks>
public StandaloneCoreApplication WithApplicationEventHandler<T>()
where T : IApplicationEventHandler
{
_handlersToAdd.Add(typeof(T));
return this;
}
/// <summary>
/// Dissociates an <see cref="IApplicationEventHandler"/> type from the application.
/// </summary>
/// <typeparam name="T">The type to dissociate.</typeparam>
/// <returns>The application.</returns>
public StandaloneCoreApplication WithoutApplicationEventHandler<T>()
where T : IApplicationEventHandler
{
_handlersToRemove.Add(typeof(T));
return this;
}
/// <summary>
/// Associates an <see cref="IApplicationEventHandler"/> type with the application.
/// </summary>
/// <param name="type">The type to associate.</param>
/// <returns>The application.</returns>
/// <remarks>Types implementing <see cref="IApplicationEventHandler"/> from within
/// an executable are not automatically discovered by Umbraco and have to be
/// explicitely associated with the application using this method.</remarks>
public StandaloneCoreApplication WithApplicationEventHandler(Type type)
{
if (type.Implements<IApplicationEventHandler>() == false)
throw new ArgumentException("Type does not implement IApplicationEventHandler.", "type");
_handlersToAdd.Add(type);
return this;
}
/// <summary>
/// Dissociates an <see cref="IApplicationEventHandler"/> type from the application.
/// </summary>
/// <param name="type">The type to dissociate.</param>
/// <returns>The application.</returns>
public StandaloneCoreApplication WithoutApplicationEventHandler(Type type)
{
if (type.Implements<IApplicationEventHandler>() == false)
throw new ArgumentException("Type does not implement IApplicationEventHandler.", "type");
_handlersToRemove.Add(type);
return this;
}
#endregion
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Persistence.Mappers;
using umbraco.interfaces;
namespace Umbraco.Core.Standalone
{
internal class StandaloneCoreBootManager : CoreBootManager
{
private readonly IEnumerable<Type> _handlersToAdd;
private readonly IEnumerable<Type> _handlersToRemove;
public StandaloneCoreBootManager(UmbracoApplicationBase umbracoApplication, IEnumerable<Type> handlersToAdd, IEnumerable<Type> handlersToRemove)
: base(umbracoApplication)
{
_handlersToAdd = handlersToAdd;
_handlersToRemove = handlersToRemove;
// this is only here to ensure references to the assemblies needed for
// the DataTypesResolver otherwise they won't be loaded into the AppDomain.
var interfacesAssemblyName = typeof(IDataType).Assembly.FullName;
}
protected override void InitializeApplicationEventsResolver()
{
base.InitializeApplicationEventsResolver();
foreach (var type in _handlersToAdd)
ApplicationEventsResolver.Current.AddType(type);
foreach (var type in _handlersToRemove)
ApplicationEventsResolver.Current.RemoveType(type);
}
protected override void InitializeResolvers()
{
base.InitializeResolvers();
//Mappers are not resolved, which could be because of a known TypeMapper issue
MappingResolver.Reset();
MappingResolver.Current = new MappingResolver(
() =>
new List<Type>
{
typeof (ContentMapper),
typeof (ContentTypeMapper),
typeof (MediaMapper),
typeof (MediaTypeMapper),
typeof (DataTypeDefinitionMapper),
typeof (UmbracoEntityMapper)
});
}
}
}

View File

@@ -692,6 +692,9 @@
<Compile Include="Services\PackagingService.cs" />
<Compile Include="Services\ServiceContext.cs" />
<Compile Include="Services\UserService.cs" />
<Compile Include="Standalone\ServiceContextManager.cs" />
<Compile Include="Standalone\StandaloneCoreApplication.cs" />
<Compile Include="Standalone\StandaloneCoreBootManager.cs" />
<Compile Include="Strings\ContentBaseExtensions.cs" />
<Compile Include="TopologicalSorter.cs" />
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;

View File

@@ -184,6 +184,32 @@ namespace Umbraco.Tests.Services
Assert.That(homeDoc.ContentTypeId, Is.EqualTo(ctHomePage.Id));
}
[Test]
public void Can_Create_And_Save_ContentType_Composition()
{
/*
* Global
* - Components
* - Category
*/
var service = ServiceContext.ContentTypeService;
var global = MockedContentTypes.CreateSimpleContentType("global", "Global");
service.Save(global);
var components = MockedContentTypes.CreateSimpleContentType("components", "Components", global);
service.Save(components);
var component = MockedContentTypes.CreateSimpleContentType("component", "Component", components);
service.Save(component);
var category = MockedContentTypes.CreateSimpleContentType("category", "Category", global);
service.Save(category);
var success = category.AddContentType(component);
Assert.That(success, Is.False);
}
private IEnumerable<IContentType> CreateContentTypeHierarchy()
{
//create the master type

View File

@@ -0,0 +1,55 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
namespace Umbraco.Web.Standalone
{
internal class ServiceContextManager : IDisposable
{
private readonly string _connectionString;
private readonly string _providerName;
private ServiceContext _serviceContext;
private readonly StandaloneApplication _application;
public ServiceContextManager(string connectionString, string providerName)
{
_connectionString = connectionString;
_providerName = providerName;
_application = StandaloneApplication.GetApplication();
_application.Start();
}
public ServiceContext Services
{
get
{
if (_serviceContext == null)
{
var dbFactory = new DefaultDatabaseFactory(_connectionString, _providerName);
var dbContext = new DatabaseContext(dbFactory);
Database.Mapper = new PetaPocoMapper();
_serviceContext = new ServiceContext(
new PetaPocoUnitOfWorkProvider(dbFactory),
new FileUnitOfWorkProvider(),
new PublishingStrategy());
//initialize the DatabaseContext
dbContext.Initialize(_providerName);
}
return _serviceContext;
}
}
public void Dispose()
{
((IDisposable)ApplicationContext.Current).Dispose();
_application.Dispose();
}
}
}

View File

@@ -9,13 +9,12 @@ namespace Umbraco.Web.Standalone
/// <summary>
/// An application standalone applications.
/// </summary>
class StandaloneApplication : UmbracoApplicationBase
internal class StandaloneApplication : UmbracoApplicationBase
{
/// <summary>
/// Initializes a new instance of the <see cref="StandaloneApplication"/> class.
/// </summary>
protected StandaloneApplication()
{ }
protected StandaloneApplication(){ }
/// <summary>
/// Provides the application boot manager.

View File

@@ -13,7 +13,7 @@ namespace Umbraco.Web.Standalone
/// <summary>
/// A boot manager for use in standalone applications.
/// </summary>
class StandaloneBootManager : CoreBootManager
internal class StandaloneBootManager : CoreBootManager
{
// fixme - could we inherit from WebBootManager?
// fixme - highly experimental, probably not complete!

View File

@@ -9,7 +9,7 @@ namespace Umbraco.Web.Standalone
/// <summary>
/// An Http context for use in standalone applications.
/// </summary>
class StandaloneHttpContext : HttpContextBase
internal class StandaloneHttpContext : HttpContextBase
{
// fixme - what shall we implement here?

View File

@@ -284,6 +284,7 @@
<Compile Include="Cache\UserCacheRefresher.cs" />
<Compile Include="Cache\UserTypeCacheRefresher.cs" />
<Compile Include="Configuration\WebRouting.cs" />
<Compile Include="Standalone\ServiceContextManager.cs" />
<Compile Include="Standalone\StandaloneApplication.cs" />
<Compile Include="Standalone\StandaloneBootManager.cs" />
<Compile Include="Standalone\StandaloneHttpContext.cs" />