Ensures the default PublishedModelFactory is always registered. Ensures AddModelsBuilder is done when adding the website (not required for the back office).

This commit is contained in:
Shannon
2021-02-01 16:53:24 +11:00
parent 624739e697
commit 2a41cec263
18 changed files with 165 additions and 128 deletions

View File

@@ -1,5 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.DependencyInjection namespace Umbraco.Core.DependencyInjection
{ {
@@ -8,7 +13,6 @@ namespace Umbraco.Core.DependencyInjection
/// </summary> /// </summary>
public static class ServiceProviderExtensions public static class ServiceProviderExtensions
{ {
/// <summary> /// <summary>
/// Creates an instance with arguments. /// Creates an instance with arguments.
/// </summary> /// </summary>
@@ -27,7 +31,7 @@ namespace Umbraco.Core.DependencyInjection
/// <summary> /// <summary>
/// Creates an instance of a service, with arguments. /// Creates an instance of a service, with arguments.
/// </summary> /// </summary>
/// <param name="serviceProvider"></param> /// <param name="serviceProvider">The <see cref="IServiceProvider"/></param>
/// <param name="type">The type of the instance.</param> /// <param name="type">The type of the instance.</param>
/// <param name="args">Named arguments.</param> /// <param name="args">Named arguments.</param>
/// <returns>An instance of the specified type.</returns> /// <returns>An instance of the specified type.</returns>
@@ -37,46 +41,17 @@ namespace Umbraco.Core.DependencyInjection
/// are retrieved from the factory.</para> /// are retrieved from the factory.</para>
/// </remarks> /// </remarks>
public static object CreateInstance(this IServiceProvider serviceProvider, Type type, params object[] args) public static object CreateInstance(this IServiceProvider serviceProvider, Type type, params object[] args)
=> ActivatorUtilities.CreateInstance(serviceProvider, type, args);
[EditorBrowsable(EditorBrowsableState.Never)]
public static PublishedModelFactory CreateDefaultPublishedModelFactory(this IServiceProvider factory)
{ {
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities TypeLoader typeLoader = factory.GetRequiredService<TypeLoader>();
// including the most annoying one, which is that it does not work on singletons (hard to fix) IPublishedValueFallback publishedValueFallback = factory.GetRequiredService<IPublishedValueFallback>();
//return factory.GetInstance(type, args); IEnumerable<Type> types = typeLoader
.GetTypes<PublishedElementModel>() // element models
// this method is essentially used to build singleton instances, so it is assumed that it would be .Concat(typeLoader.GetTypes<PublishedContentModel>()); // content models
// more expensive to build and cache a dynamic method ctor than to simply invoke the ctor, as we do return new PublishedModelFactory(types, publishedValueFallback);
// here - this can be discussed
// TODO: we currently try the ctor with most parameters, but we could want to fall back to others
//var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault();
//if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}.");
//var ctorParameters = ctor.GetParameters();
//var ctorArgs = new object[ctorParameters.Length];
//var availableArgs = new List<object>(args);
//var i = 0;
//foreach (var parameter in ctorParameters)
//{
// // no! IsInstanceOfType is not ok here
// // ReSharper disable once UseMethodIsInstanceOfType
// var idx = availableArgs.FindIndex(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
// if (idx >= 0)
// {
// // Found a suitable supplied argument
// ctorArgs[i++] = availableArgs[idx];
// // A supplied argument can be used at most once
// availableArgs.RemoveAt(idx);
// }
// else
// {
// // None of the provided arguments is suitable: get an instance from the factory
// ctorArgs[i++] = serviceProvider.GetRequiredService(parameter.ParameterType);
// }
//}
//return ctor.Invoke(ctorArgs);
return ActivatorUtilities.CreateInstance(serviceProvider, type, args);
} }
} }
} }

View File

@@ -1,13 +1,12 @@
// Copyright (c) Umbraco. // Copyright (c) Umbraco.
// See LICENSE for more details. // See LICENSE for more details.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Umbraco.Core.Events; using Umbraco.Core.Events;
namespace Umbraco.Core.DependencyInjection namespace Umbraco.Core.DependencyInjection
{ {
/// <summary> /// <summary>
/// Contains extensions methods for <see cref="IUmbracoBuilder"/> used for registering event handlers. /// Contains extensions methods for <see cref="IUmbracoBuilder"/> used for registering event handlers.
/// </summary> /// </summary>
@@ -56,30 +55,5 @@ namespace Umbraco.Core.DependencyInjection
return builder; return builder;
} }
// This is required because the default implementation doesn't implement Equals or GetHashCode.
// see: https://github.com/dotnet/runtime/issues/47262
private class UniqueServiceDescriptor : ServiceDescriptor, IEquatable<UniqueServiceDescriptor>
{
public UniqueServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime)
: base(serviceType, implementationType, lifetime)
{
}
public override bool Equals(object obj) => Equals(obj as UniqueServiceDescriptor);
public bool Equals(UniqueServiceDescriptor other) => other != null && Lifetime == other.Lifetime && EqualityComparer<Type>.Default.Equals(ServiceType, other.ServiceType) && EqualityComparer<Type>.Default.Equals(ImplementationType, other.ImplementationType) && EqualityComparer<object>.Default.Equals(ImplementationInstance, other.ImplementationInstance) && EqualityComparer<Func<IServiceProvider, object>>.Default.Equals(ImplementationFactory, other.ImplementationFactory);
public override int GetHashCode()
{
int hashCode = 493849952;
hashCode = hashCode * -1521134295 + Lifetime.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<Type>.Default.GetHashCode(ServiceType);
hashCode = hashCode * -1521134295 + EqualityComparer<Type>.Default.GetHashCode(ImplementationType);
hashCode = hashCode * -1521134295 + EqualityComparer<object>.Default.GetHashCode(ImplementationInstance);
hashCode = hashCode * -1521134295 + EqualityComparer<Func<IServiceProvider, object>>.Default.GetHashCode(ImplementationFactory);
return hashCode;
}
}
} }
} }

View File

@@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -216,6 +217,11 @@ namespace Umbraco.Core.DependencyInjection
? (IServerRoleAccessor)new SingleServerRoleAccessor() ? (IServerRoleAccessor)new SingleServerRoleAccessor()
: new ElectedServerRoleAccessor(f.GetRequiredService<IServerRegistrationService>()); : new ElectedServerRoleAccessor(f.GetRequiredService<IServerRegistrationService>());
}); });
// For Umbraco to work it must have the default IPublishedModelFactory
// which may be replaced by models builder but the default is required to make plain old IPublishedContent
// instances.
Services.AddSingleton<IPublishedModelFactory>(factory => factory.CreateDefaultPublishedModelFactory());
} }
} }
} }

View File

@@ -0,0 +1,45 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
namespace Umbraco.Core.DependencyInjection
{
/// <summary>
/// A custom <see cref="ServiceDescriptor"/> that supports unique checking
/// </summary>
/// <remarks>
/// This is required because the default implementation doesn't implement Equals or GetHashCode.
/// see: https://github.com/dotnet/runtime/issues/47262
/// </remarks>
public sealed class UniqueServiceDescriptor : ServiceDescriptor, IEquatable<UniqueServiceDescriptor>
{
/// <summary>
/// Initializes a new instance of the <see cref="UniqueServiceDescriptor"/> class.
/// </summary>
public UniqueServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime)
: base(serviceType, implementationType, lifetime)
{
}
/// <inheritdoc/>
public override bool Equals(object obj) => Equals(obj as UniqueServiceDescriptor);
/// <inheritdoc/>
public bool Equals(UniqueServiceDescriptor other) => other != null && Lifetime == other.Lifetime && EqualityComparer<Type>.Default.Equals(ServiceType, other.ServiceType) && EqualityComparer<Type>.Default.Equals(ImplementationType, other.ImplementationType) && EqualityComparer<object>.Default.Equals(ImplementationInstance, other.ImplementationInstance) && EqualityComparer<Func<IServiceProvider, object>>.Default.Equals(ImplementationFactory, other.ImplementationFactory);
/// <inheritdoc/>
public override int GetHashCode()
{
int hashCode = 493849952;
hashCode = (hashCode * -1521134295) + Lifetime.GetHashCode();
hashCode = (hashCode * -1521134295) + EqualityComparer<Type>.Default.GetHashCode(ServiceType);
hashCode = (hashCode * -1521134295) + EqualityComparer<Type>.Default.GetHashCode(ImplementationType);
hashCode = (hashCode * -1521134295) + EqualityComparer<object>.Default.GetHashCode(ImplementationInstance);
hashCode = (hashCode * -1521134295) + EqualityComparer<Func<IServiceProvider, object>>.Default.GetHashCode(ImplementationFactory);
return hashCode;
}
}
}

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
@@ -17,8 +17,11 @@ namespace Umbraco.Core.Models.PublishedContent
private class ModelInfo private class ModelInfo
{ {
public Type ParameterType { get; set; } public Type ParameterType { get; set; }
public Func<object, IPublishedValueFallback, object> Ctor { get; set; } public Func<object, IPublishedValueFallback, object> Ctor { get; set; }
public Type ModelType { get; set; } public Type ModelType { get; set; }
public Func<IList> ListCtor { get; set; } public Func<IList> ListCtor { get; set; }
} }
@@ -36,8 +39,7 @@ namespace Umbraco.Core.Models.PublishedContent
/// PublishedContentModelFactoryResolver.Current.SetFactory(factory); /// PublishedContentModelFactoryResolver.Current.SetFactory(factory);
/// </code> /// </code>
/// </remarks> /// </remarks>
public PublishedModelFactory(IEnumerable<Type> types, public PublishedModelFactory(IEnumerable<Type> types, IPublishedValueFallback publishedValueFallback)
IPublishedValueFallback publishedValueFallback)
{ {
var modelInfos = new Dictionary<string, ModelInfo>(StringComparer.InvariantCultureIgnoreCase); var modelInfos = new Dictionary<string, ModelInfo>(StringComparer.InvariantCultureIgnoreCase);
var modelTypeMap = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase); var modelTypeMap = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);

View File

@@ -1,5 +1,6 @@
using System; using System;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Umbraco.Core.DependencyInjection; using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events; using Umbraco.Core.Events;
using Umbraco.Core.Services.Changes; using Umbraco.Core.Services.Changes;
@@ -19,13 +20,24 @@ namespace Umbraco.Infrastructure.DependencyInjection
/// <summary> /// <summary>
/// Adds distributed cache support /// Adds distributed cache support
/// </summary> /// </summary>
/// <remarks>
/// This is still required for websites that are not load balancing because this ensures that sites hosted
/// with managed hosts like IIS/etc... work correctly when AppDomains are running in parallel.
/// </remarks>
public static IUmbracoBuilder AddDistributedCache(this IUmbracoBuilder builder) public static IUmbracoBuilder AddDistributedCache(this IUmbracoBuilder builder)
{ {
var distCacheBinder = new UniqueServiceDescriptor(typeof(IDistributedCacheBinder), typeof(DistributedCacheBinder), ServiceLifetime.Singleton);
if (builder.Services.Contains(distCacheBinder))
{
// if this is called more than once just exit
return builder;
}
builder.Services.Add(distCacheBinder);
builder.SetDatabaseServerMessengerCallbacks(GetCallbacks); builder.SetDatabaseServerMessengerCallbacks(GetCallbacks);
builder.SetServerMessenger<BatchedDatabaseServerMessenger>(); builder.SetServerMessenger<BatchedDatabaseServerMessenger>();
builder.AddNotificationHandler<UmbracoApplicationStarting, DatabaseServerMessengerNotificationHandler>(); builder.AddNotificationHandler<UmbracoApplicationStarting, DatabaseServerMessengerNotificationHandler>();
builder.Services.AddUnique<IDistributedCacheBinder, DistributedCacheBinder>();
return builder; return builder;
} }

View File

@@ -3,8 +3,8 @@ using System.Text;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Umbraco.Core.Configuration; using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.Models;
using Umbraco.Core.IO;
using Umbraco.Core.Hosting; using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
namespace Umbraco.ModelsBuilder.Embedded.Building namespace Umbraco.ModelsBuilder.Embedded.Building
{ {

View File

@@ -85,8 +85,16 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
/// </summary> /// </summary>
public static IUmbracoBuilder AddModelsBuilder(this IUmbracoBuilder builder) public static IUmbracoBuilder AddModelsBuilder(this IUmbracoBuilder builder)
{ {
var umbServices = new UniqueServiceDescriptor(typeof(UmbracoServices), typeof(UmbracoServices), ServiceLifetime.Singleton);
if (builder.Services.Contains(umbServices))
{
// if this ext method is called more than once just exit
return builder;
}
builder.Services.Add(umbServices);
builder.AddPureLiveRazorEngine(); builder.AddPureLiveRazorEngine();
builder.Services.AddSingleton<UmbracoServices>();
// TODO: I feel like we could just do builder.AddNotificationHandler<ModelsBuilderNotificationHandler>() and it // TODO: I feel like we could just do builder.AddNotificationHandler<ModelsBuilderNotificationHandler>() and it
// would automatically just register for all implemented INotificationHandler{T}? // would automatically just register for all implemented INotificationHandler{T}?
@@ -96,13 +104,16 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
builder.AddNotificationHandler<UmbracoApplicationStarting, LiveModelsProvider>(); builder.AddNotificationHandler<UmbracoApplicationStarting, LiveModelsProvider>();
builder.AddNotificationHandler<UmbracoRequestEnd, LiveModelsProvider>(); builder.AddNotificationHandler<UmbracoRequestEnd, LiveModelsProvider>();
builder.AddNotificationHandler<UmbracoApplicationStarting, OutOfDateModelsStatus>(); builder.AddNotificationHandler<UmbracoApplicationStarting, OutOfDateModelsStatus>();
builder.Services.AddUnique<ModelsGenerator>(); builder.Services.AddSingleton<ModelsGenerator>();
builder.Services.AddUnique<LiveModelsProvider>(); builder.Services.AddSingleton<LiveModelsProvider>();
builder.Services.AddUnique<OutOfDateModelsStatus>(); builder.Services.AddSingleton<OutOfDateModelsStatus>();
builder.Services.AddUnique<ModelsGenerationError>(); builder.Services.AddSingleton<ModelsGenerationError>();
builder.Services.AddUnique<PureLiveModelFactory>(); builder.Services.AddSingleton<PureLiveModelFactory>();
builder.Services.AddUnique<IPublishedModelFactory>(factory =>
// This is what the community MB would replace, all of the above services are fine to be registered
// even if the community MB is in place.
builder.Services.AddSingleton<IPublishedModelFactory>(factory =>
{ {
ModelsBuilderSettings config = factory.GetRequiredService<IOptions<ModelsBuilderSettings>>().Value; ModelsBuilderSettings config = factory.GetRequiredService<IOptions<ModelsBuilderSettings>>().Value;
if (config.ModelsMode == ModelsMode.PureLive) if (config.ModelsMode == ModelsMode.PureLive)
@@ -111,12 +122,7 @@ namespace Umbraco.ModelsBuilder.Embedded.DependencyInjection
} }
else else
{ {
TypeLoader typeLoader = factory.GetRequiredService<TypeLoader>(); return factory.CreateDefaultPublishedModelFactory();
IPublishedValueFallback publishedValueFallback = factory.GetRequiredService<IPublishedValueFallback>();
IEnumerable<Type> types = typeLoader
.GetTypes<PublishedElementModel>() // element models
.Concat(typeLoader.GetTypes<PublishedContentModel>()); // content models
return new PublishedModelFactory(types, publishedValueFallback);
} }
}); });

View File

@@ -45,10 +45,7 @@ namespace Umbraco.ModelsBuilder.Embedded
/// <summary> /// <summary>
/// Handles the <see cref="UmbracoApplicationStarting"/> notification /// Handles the <see cref="UmbracoApplicationStarting"/> notification
/// </summary> /// </summary>
public void Handle(UmbracoApplicationStarting notification) public void Handle(UmbracoApplicationStarting notification) => Install();
{
Install();
}
private void Install() private void Install()
{ {

View File

@@ -53,7 +53,7 @@ namespace Umbraco.ModelsBuilder.Embedded
} }
/// <summary> /// <summary>
/// Handles the <see cref="ServerVariablesParsing"/> notification /// Handles the <see cref="ServerVariablesParsing"/> notification to add custom urls and MB mode
/// </summary> /// </summary>
public void Handle(ServerVariablesParsing notification) public void Handle(ServerVariablesParsing notification)
{ {
@@ -93,7 +93,7 @@ namespace Umbraco.ModelsBuilder.Embedded
{ {
var settings = new Dictionary<string, object> var settings = new Dictionary<string, object>
{ {
{"mode", _config.ModelsMode.ToString()} {"mode", _config.ModelsMode.ToString() }
}; };
return settings; return settings;
@@ -188,13 +188,12 @@ namespace Umbraco.ModelsBuilder.Embedded
{ {
// both are pure - report, and if different versions, restart // both are pure - report, and if different versions, restart
// if same version... makes no sense... and better not restart (loops?) // if same version... makes no sense... and better not restart (loops?)
var sourceVersion = notification.SourceType.Assembly.GetName().Version; Version sourceVersion = notification.SourceType.Assembly.GetName().Version;
var modelVersion = notification.ModelType.Assembly.GetName().Version; Version modelVersion = notification.ModelType.Assembly.GetName().Version;
notification.Message.Append(" Both view and content models are PureLive, with "); notification.Message.Append(" Both view and content models are PureLive, with ");
notification.Message.Append(sourceVersion == modelVersion notification.Message.Append(sourceVersion == modelVersion
? "same version. The application is in an unstable state and should be restarted." ? "same version. The application is in an unstable state and should be restarted."
: "different versions. The application is in an unstable state and is going to be restarted."); : "different versions. The application is in an unstable state and should be restarted.");
notification.Restart = sourceVersion != modelVersion;
} }
} }
} }

View File

@@ -1,10 +1,10 @@
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Umbraco.Core.Configuration; using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.Models;
using Umbraco.Core.Hosting;
namespace Umbraco.ModelsBuilder.Embedded namespace Umbraco.ModelsBuilder.Embedded
{ {
@@ -13,6 +13,9 @@ namespace Umbraco.ModelsBuilder.Embedded
private readonly ModelsBuilderSettings _config; private readonly ModelsBuilderSettings _config;
private readonly IHostingEnvironment _hostingEnvironment; private readonly IHostingEnvironment _hostingEnvironment;
/// <summary>
/// Initializes a new instance of the <see cref="ModelsGenerationError"/> class.
/// </summary>
public ModelsGenerationError(IOptions<ModelsBuilderSettings> config, IHostingEnvironment hostingEnvironment) public ModelsGenerationError(IOptions<ModelsBuilderSettings> config, IHostingEnvironment hostingEnvironment)
{ {
_config = config.Value; _config = config.Value;
@@ -22,7 +25,10 @@ namespace Umbraco.ModelsBuilder.Embedded
public void Clear() public void Clear()
{ {
var errFile = GetErrFile(); var errFile = GetErrFile();
if (errFile == null) return; if (errFile == null)
{
return;
}
// "If the file to be deleted does not exist, no exception is thrown." // "If the file to be deleted does not exist, no exception is thrown."
File.Delete(errFile); File.Delete(errFile);
@@ -31,7 +37,10 @@ namespace Umbraco.ModelsBuilder.Embedded
public void Report(string message, Exception e) public void Report(string message, Exception e)
{ {
var errFile = GetErrFile(); var errFile = GetErrFile();
if (errFile == null) return; if (errFile == null)
{
return;
}
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append(message); sb.Append(message);
@@ -47,14 +56,18 @@ namespace Umbraco.ModelsBuilder.Embedded
public string GetLastError() public string GetLastError()
{ {
var errFile = GetErrFile(); var errFile = GetErrFile();
if (errFile == null) return null; if (errFile == null)
{
return null;
}
try try
{ {
return File.ReadAllText(errFile); return File.ReadAllText(errFile);
} }
catch // accepted catch
{ {
// accepted
return null; return null;
} }
} }
@@ -63,7 +76,9 @@ namespace Umbraco.ModelsBuilder.Embedded
{ {
var modelsDirectory = _config.ModelsDirectoryAbsolute(_hostingEnvironment); var modelsDirectory = _config.ModelsDirectoryAbsolute(_hostingEnvironment);
if (!Directory.Exists(modelsDirectory)) if (!Directory.Exists(modelsDirectory))
{
return null; return null;
}
return Path.Combine(modelsDirectory, "models.err"); return Path.Combine(modelsDirectory, "models.err");
} }

View File

@@ -8,19 +8,31 @@ using Umbraco.Web.Cache;
namespace Umbraco.ModelsBuilder.Embedded namespace Umbraco.ModelsBuilder.Embedded
{ {
/// <summary>
/// Used to track if ModelsBuilder models are out of date/stale
/// </summary>
public sealed class OutOfDateModelsStatus : INotificationHandler<UmbracoApplicationStarting> public sealed class OutOfDateModelsStatus : INotificationHandler<UmbracoApplicationStarting>
{ {
private readonly ModelsBuilderSettings _config; private readonly ModelsBuilderSettings _config;
private readonly IHostingEnvironment _hostingEnvironment; private readonly IHostingEnvironment _hostingEnvironment;
/// <summary>
/// Initializes a new instance of the <see cref="OutOfDateModelsStatus"/> class.
/// </summary>
public OutOfDateModelsStatus(IOptions<ModelsBuilderSettings> config, IHostingEnvironment hostingEnvironment) public OutOfDateModelsStatus(IOptions<ModelsBuilderSettings> config, IHostingEnvironment hostingEnvironment)
{ {
_config = config.Value; _config = config.Value;
_hostingEnvironment = hostingEnvironment; _hostingEnvironment = hostingEnvironment;
} }
/// <summary>
/// Gets a value indicating whether flagging out of date models is enabled
/// </summary>
public bool IsEnabled => _config.FlagOutOfDateModels; public bool IsEnabled => _config.FlagOutOfDateModels;
/// <summary>
/// Gets a value indicating whether models are out of date
/// </summary>
public bool IsOutOfDate public bool IsOutOfDate
{ {
get get
@@ -38,10 +50,7 @@ namespace Umbraco.ModelsBuilder.Embedded
/// <summary> /// <summary>
/// Handles the <see cref="UmbracoApplicationStarting"/> notification /// Handles the <see cref="UmbracoApplicationStarting"/> notification
/// </summary> /// </summary>
public void Handle(UmbracoApplicationStarting notification) public void Handle(UmbracoApplicationStarting notification) => Install();
{
Install();
}
private void Install() private void Install()
{ {

View File

@@ -20,6 +20,9 @@ namespace Umbraco.ModelsBuilder.Embedded
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory; private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
private readonly IShortStringHelper _shortStringHelper; private readonly IShortStringHelper _shortStringHelper;
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoServices"/> class.
/// </summary>
public UmbracoServices( public UmbracoServices(
IContentTypeService contentTypeService, IContentTypeService contentTypeService,
IMediaTypeService mediaTypeService, IMediaTypeService mediaTypeService,

View File

@@ -10,11 +10,14 @@ namespace Umbraco.Core.Events
/// </summary> /// </summary>
public class UmbracoRequestEnd : INotification public class UmbracoRequestEnd : INotification
{ {
public UmbracoRequestEnd(HttpContext httpContext) /// <summary>
{ /// Initializes a new instance of the <see cref="UmbracoRequestEnd"/> class.
HttpContext = httpContext; /// </summary>
} public UmbracoRequestEnd(HttpContext httpContext) => HttpContext = httpContext;
/// <summary>
/// Gets the <see cref="HttpContext"/>
/// </summary>
public HttpContext HttpContext { get; } public HttpContext HttpContext { get; }
} }
} }

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Text; using System.Text;
using Umbraco.Core.Events; using Umbraco.Core.Events;
@@ -22,22 +22,17 @@ namespace Umbraco.Web.Common.ModelBinders
/// <summary> /// <summary>
/// Gets the type of the source object. /// Gets the type of the source object.
/// </summary> /// </summary>
public Type SourceType { get; set; } public Type SourceType { get; }
/// <summary> /// <summary>
/// Gets the type of the view model. /// Gets the type of the view model.
/// </summary> /// </summary>
public Type ModelType { get; set; } public Type ModelType { get; }
/// <summary> /// <summary>
/// Gets the message string builder. /// Gets the message string builder.
/// </summary> /// </summary>
/// <remarks>Handlers of the event can append text to the message.</remarks> /// <remarks>Handlers of the event can append text to the message.</remarks>
public StringBuilder Message { get; } public StringBuilder Message { get; }
/// <summary>
/// Gets or sets a value indicating whether the application should restart.
/// </summary>
public bool Restart { get; set; }
} }
} }

View File

@@ -49,14 +49,6 @@ namespace Umbraco.Web.UI.NetCore
.AddBackOffice() .AddBackOffice()
.AddWebsite() .AddWebsite()
.AddComposers() .AddComposers()
// TODO: This call and AddDistributedCache are interesting ones. They are both required for back office and front-end to render
// but we don't want to force people to call so many of these ext by default and want to keep all of this relatively simple.
// but we still need to allow the flexibility for people to use their own ModelsBuilder. In that case people can call a different
// AddModelsBuilderCommunity (or whatever) after our normal calls to replace our services.
// So either we call AddModelsBuilder within AddBackOffice AND AddWebsite just like we do with AddDistributedCache or we
// have a top level method to add common things required for backoffice/frontend like .AddCommon()
// or we allow passing in options to these methods to configure what happens within them.
.AddModelsBuilder()
.Build(); .Build();
#pragma warning restore IDE0022 // Use expression body for methods #pragma warning restore IDE0022 // Use expression body for methods

View File

@@ -6,6 +6,7 @@ using Umbraco.Core.DependencyInjection;
using Umbraco.Extensions; using Umbraco.Extensions;
using Umbraco.Infrastructure.DependencyInjection; using Umbraco.Infrastructure.DependencyInjection;
using Umbraco.Infrastructure.PublishedCache.DependencyInjection; using Umbraco.Infrastructure.PublishedCache.DependencyInjection;
using Umbraco.ModelsBuilder.Embedded.DependencyInjection;
using Umbraco.Web.Common.Routing; using Umbraco.Web.Common.Routing;
using Umbraco.Web.Website.Collections; using Umbraco.Web.Website.Collections;
using Umbraco.Web.Website.Controllers; using Umbraco.Web.Website.Controllers;
@@ -43,7 +44,9 @@ namespace Umbraco.Web.Website.DependencyInjection
builder.Services.AddSingleton<IUmbracoRenderingDefaults, UmbracoRenderingDefaults>(); builder.Services.AddSingleton<IUmbracoRenderingDefaults, UmbracoRenderingDefaults>();
builder.Services.AddSingleton<IRoutableDocumentFilter, RoutableDocumentFilter>(); builder.Services.AddSingleton<IRoutableDocumentFilter, RoutableDocumentFilter>();
builder.AddDistributedCache(); builder
.AddDistributedCache()
.AddModelsBuilder();
return builder; return builder;
} }

View File

@@ -21,6 +21,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" /> <ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" /> <ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj" />
<ProjectReference Include="..\Umbraco.ModelsBuilder.Embedded\Umbraco.ModelsBuilder.Embedded.csproj" />
<ProjectReference Include="..\Umbraco.Web.Common\Umbraco.Web.Common.csproj" /> <ProjectReference Include="..\Umbraco.Web.Common\Umbraco.Web.Common.csproj" />
</ItemGroup> </ItemGroup>