Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add XamlObjectCreationFactory to improve the performance of XAML creation of objects #4

Open
wants to merge 13 commits into
base: dev
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Concurrent;

namespace System.Xaml.Schema
{
public static class XamlObjectCreationFactory
{
public static void RegisterCreator<T>(Func<T> creator)
{
if (creator == null) throw new ArgumentNullException(nameof(creator));
RegisterCreator(typeof(T), () => creator());
}

public static void RegisterCreator(Type type, Func<object> creator)
{
if (type == null) throw new ArgumentNullException(nameof(type));
s_xamlObjectCreatorDictionary[type] = creator ?? throw new ArgumentNullException(nameof(creator));

HasBeenRegister = true;
}

public static void RegisterTypeCreator(Func<Type, Func<object>> typeCreator)
{
_typeCreator = typeCreator;
HasBeenRegister = true;
}

internal static bool HasBeenRegister { get; private set; }

private static Func<Type, Func<object>> _typeCreator;

internal static bool TryGetCreator(Type type, out Func<object> creator)
{
if (_typeCreator != null)
{
creator = _typeCreator(type);
if (creator != null)
{
return true;
}
}

return s_xamlObjectCreatorDictionary.TryGetValue(type, out creator);
}

private static readonly ConcurrentDictionary<Type, Func<object>> s_xamlObjectCreatorDictionary =
new ConcurrentDictionary<Type, Func<object>>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class XamlTypeInvoker
internal MethodInfo EnumeratorMethod { get; set; }
private XamlType _xamlType;

private Action<object> _constructorDelegate;
private Func<object> _instanceCreatorDelegate;

private ThreeValuedBool _isPublic;

Expand Down Expand Up @@ -290,20 +290,13 @@ public static object CreateInstance(XamlTypeInvoker type)
{
return null;
}
object inst = CallCtorDelegate(type);
object inst = type._instanceCreatorDelegate();
return inst;
}

#if TARGETTING35SP1
#else
#endif
private static object CallCtorDelegate(XamlTypeInvoker type)
{
object inst = FormatterServices.GetUninitializedObject(type._xamlType.UnderlyingType);
InvokeDelegate(type._constructorDelegate, inst);
return inst;
}

private static void InvokeDelegate(Action<object> action, object argument)
{
action.Invoke(argument);
Expand All @@ -315,10 +308,21 @@ private static void InvokeDelegate(Action<object> action, object argument)
// returns true if a delegate is available, false if not
private static bool EnsureConstructorDelegate(XamlTypeInvoker type)
{
if (type._constructorDelegate != null)
if (type._instanceCreatorDelegate != null)
{
return true;
}
Type underlyingType = null;
if (XamlObjectCreationFactory.HasBeenRegister)
{
underlyingType = type._xamlType.UnderlyingType.UnderlyingSystemType;
if (XamlObjectCreationFactory.TryGetCreator(underlyingType, out Func<object> creator))
{
type._instanceCreatorDelegate = creator;
return true;
}
}

if (!type.IsPublic)
{
return false;
Expand All @@ -333,7 +337,8 @@ private static bool EnsureConstructorDelegate(XamlTypeInvoker type)
return false;
}

Type underlyingType = type._xamlType.UnderlyingType.UnderlyingSystemType;
underlyingType ??= type._xamlType.UnderlyingType.UnderlyingSystemType;

// Look up public ctors only, for equivalence with Activator.CreateInstance
ConstructorInfo tConstInfo = underlyingType.GetConstructor(Type.EmptyTypes);
if (tConstInfo == null)
Expand All @@ -352,9 +357,14 @@ private static bool EnsureConstructorDelegate(XamlTypeInvoker type)
}
IntPtr constPtr = tConstInfo.MethodHandle.GetFunctionPointer();
// This requires Reflection Permission
Action<object> ctorDelegate = ctorDelegate =
Action<object> ctorDelegate =
(Action<object>)s_actionCtor.Invoke(new object[] { null, constPtr });
type._constructorDelegate = ctorDelegate;
type._instanceCreatorDelegate = () =>
{
object inst = FormatterServices.GetUninitializedObject(type._xamlType.UnderlyingType);
InvokeDelegate(ctorDelegate, inst);
return inst;
};
return true;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/Microsoft.DotNet.Wpf/src/System.Xaml/ref/System.Xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,4 +1106,11 @@ public XamlValueConverter(System.Type converterType, System.Xaml.XamlType target
public static bool operator !=(System.Xaml.Schema.XamlValueConverter<TConverterBase> converter1, System.Xaml.Schema.XamlValueConverter<TConverterBase> converter2) { throw null; }
public override string ToString() { throw null; }
}

public static class XamlObjectCreationFactory
{
public static void RegisterCreator<T>(Func<T> creator) { }
public static void RegisterCreator(Type type, Func<object> creator) { }
public static void RegisterTypeCreator(Func<Type, Func<object>> typeCreator) { }
}
}