Browse Source

Build XAML namespace registry dynamically.

Each time a namespace is not found, look for any assemblies loaded since the last scan and scan them for XmlnsDefinitionAttribute.
pull/413/head
Steven Kirk 10 years ago
parent
commit
0c20b41377
  1. 114
      src/Markup/Perspex.Markup.Xaml/Context/PerspexNamespaceRegistry.cs
  2. 30
      src/Markup/Perspex.Markup.Xaml/Context/PerspexRuntimeTypeSource.cs
  3. 2
      src/Markup/Perspex.Markup.Xaml/OmniXAML
  4. 1
      src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

114
src/Markup/Perspex.Markup.Xaml/Context/PerspexNamespaceRegistry.cs

@ -0,0 +1,114 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using OmniXaml.Builder;
using OmniXaml.Typing;
using Perspex.Controls;
using Perspex.Markup.Xaml.Templates;
using Perspex.Media;
using Perspex.Metadata;
using Perspex.Platform;
using Perspex.Styling;
namespace Perspex.Markup.Xaml.Context
{
public class PerspexNamespaceRegistry : INamespaceRegistry
{
private const string PerspexNs = "https://github.com/perspex";
private static readonly IEnumerable<Assembly> ForcedAssemblies = new[]
{
typeof(PerspexObject).GetTypeInfo().Assembly,
typeof(Control).GetTypeInfo().Assembly,
typeof(Style).GetTypeInfo().Assembly,
typeof(DataTemplate).GetTypeInfo().Assembly,
typeof(SolidColorBrush).GetTypeInfo().Assembly,
typeof(IValueConverter).GetTypeInfo().Assembly,
};
private List<XamlNamespace> _namespaces = new List<XamlNamespace>();
private List<PrefixRegistration> _prefixes = new List<PrefixRegistration>();
private List<Assembly> _scanned = new List<Assembly>();
public PerspexNamespaceRegistry()
{
ScanAssemblies(ForcedAssemblies);
ScanNewAssemblies();
RegisterPrefix(new PrefixRegistration(string.Empty, PerspexNs));
}
public IEnumerable<PrefixRegistration> RegisteredPrefixes => _prefixes;
public void AddNamespace(XamlNamespace xamlNamespace)
{
_namespaces.Add(xamlNamespace);
}
public Namespace GetNamespace(string name)
{
var result = _namespaces.FirstOrDefault(x => x.Name == name);
if (result == null)
{
ScanNewAssemblies();
result = _namespaces.FirstOrDefault(x => x.Name == name);
}
return result;
}
public Namespace GetNamespaceByPrefix(string prefix)
{
var ns = _prefixes.FirstOrDefault(x => x.Prefix == prefix)?.Ns;
return (ns != null) ? GetNamespace(ns) : null;
}
public void RegisterPrefix(PrefixRegistration prefixRegistration)
{
_prefixes.Add(prefixRegistration);
}
private void ScanAssemblies(IEnumerable<Assembly> assemblies)
{
foreach (var assembly in assemblies)
{
var namespaces = assembly.GetCustomAttributes<XmlnsDefinitionAttribute>()
.Select(x => new { x.XmlNamespace, x.ClrNamespace })
.GroupBy(x => x.XmlNamespace);
foreach (var nsa in namespaces)
{
var xamlNamespace = _namespaces.FirstOrDefault(x => x.Name == nsa.Key);
if (xamlNamespace == null)
{
xamlNamespace = new XamlNamespace(nsa.Key);
_namespaces.Add(xamlNamespace);
}
var clrNamespaces = namespaces.SelectMany(x => x).Select(x => x.ClrNamespace);
xamlNamespace.Addresses.Add(new ConfiguredAssemblyWithNamespaces(assembly, clrNamespaces));
}
_scanned.Add(assembly);
}
}
private void ScanNewAssemblies()
{
IEnumerable<Assembly> assemblies = PerspexLocator.Current
.GetService<IPclPlatformWrapper>()
?.GetLoadedAssemblies();
if (assemblies != null)
{
assemblies = assemblies.Except(_scanned);
ScanAssemblies(assemblies);
}
}
}
}

30
src/Markup/Perspex.Markup.Xaml/Context/PerspexRuntimeTypeSource.cs

@ -34,14 +34,12 @@ namespace Perspex.Markup.Xaml.Context
typeof(SolidColorBrush).GetTypeInfo().Assembly,
typeof(IValueConverter).GetTypeInfo().Assembly,
};
private const string PerspexNs = "https://github.com/perspex";
private readonly RuntimeTypeSource inner;
public PerspexRuntimeTypeSource(ITypeFactory typeFactory)
{
var namespaceRegistry = CreateNamespaceRegistry();
var namespaceRegistry = new PerspexNamespaceRegistry();
var featureProvider = new TypeFeatureProvider(GetConverterProvider());
LoadFeatureProvider(featureProvider);
var typeRepository = new PerspexTypeRepository(namespaceRegistry, typeFactory, featureProvider);
@ -93,30 +91,6 @@ namespace Perspex.Markup.Xaml.Context
}
}
private static INamespaceRegistry CreateNamespaceRegistry()
{
var xamlNamespaceRegistry = new NamespaceRegistry();
foreach (var nsa in
ScannedAssemblies
.Distinct()
.SelectMany(asm
=> asm.GetCustomAttributes<XmlnsDefinitionAttribute>().Select(attr => new { asm, attr }))
.GroupBy(entry => entry.attr.XmlNamespace))
{
var def = XamlNamespace.Map(nsa.Key)
.With(nsa.GroupBy(x => x.asm).Select(
a => Route.Assembly(a.Key)
.WithNamespaces(a.Select(entry => entry.attr.ClrNamespace).ToList())
));
xamlNamespaceRegistry.AddNamespace(def);
}
xamlNamespaceRegistry.RegisterPrefix(new PrefixRegistration(string.Empty, PerspexNs));
return xamlNamespaceRegistry;
}
private static ITypeConverterProvider GetConverterProvider()
{
var typeConverterProvider = new TypeConverterProvider();

2
src/Markup/Perspex.Markup.Xaml/OmniXAML

@ -1 +1 @@
Subproject commit c2ffcccc82514d19adeb74220e0490ac480c7473
Subproject commit 2b28639da15e5f43f4b713e0b115d1bb41679cc6

1
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@ -42,6 +42,7 @@
</Compile>
<Compile Include="Context\NameScopeWrapper.cs" />
<Compile Include="Context\PerspexAttachableXamlMember.cs" />
<Compile Include="Context\PerspexNamespaceRegistry.cs" />
<Compile Include="Context\PerspexObjectAssembler.cs" />
<Compile Include="Context\PerspexParserFactory.cs" />
<Compile Include="Context\PerspexRuntimeTypeSource.cs" />

Loading…
Cancel
Save