<Application.Resources> <SolidColorBrush x:Key="HeaderBrush" Color="Black" /> <Application.Resources>
<TextBlock x:Name="header" Foreground="{StaticResource HeaderBrush}" />
header.Foreground = (SolidColorBrush)Application.Current.Resources["HeaderBrush"];
header.Foreground = AppResources.HeaderBrush;
<#@ template debug="false" hostSpecific="true" language="C#" #> <#@ output extension=".cs" #>
using System.Windows; namespace <#=ProjectDefaultNamespace#> { public static class AppResources { <# foreach (var resource in ResourcesFromFile("/App.xaml")) { OutputPropery(resource); } #> } }
private VSProject _vsProject; public VSProject VSProject { get { if (_vsProject == null) { var serviceProvider = (IServiceProvider) Host; var dte = (DTE)serviceProvider.GetService(typeof (DTE)); _vsProject = (VSProject)dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject.Object; } return _vsProject; } }
private string _projectDefaultNamespace; public string ProjectDefaultNamespace { get { if (_projectDefaultNamespace == null) _projectDefaultNamespace = VSProject.Project.Properties.Item("DefaultNamespace").Value.ToString(); return _projectDefaultNamespace; } }
var control = new CustomNamespace.CustomControl();
using CustomNamespace; var control = new CustomControl();
<local:CustomControl />
xmlns:local="clr-namespace:CustomNamespace"
xmlns="clr-namespace:CustomNamespace"
<CustomControl />
<SolidColorBrush Color="Red" />
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Media")] [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]
<local:CustomControl xmlns:local="clr-namespace:CustomNamespace" />
public interface ITypeResolver { string ResolveTypeFullName(string localTagName); }
public class ExplicitNamespaceResolver : ITypeResolver { private string _singleNamespace; public ExplicitNamespaceResolver(string singleNamespace) { _singleNamespace = singleNamespace; } public string ResolveTypeFullName(string localTagName) { return _singleNamespace + "." + localTagName; } }
public class XmlnsAliasResolver : ITypeResolver { private readonly List<Tuple<string, Assembly>> _registeredNamespaces = new List<Tuple<string, Assembly>>(); public XmlnsAliasResolver(VSProject project, string alias) { foreach (var reference in project.References.OfType<Reference>() .Where(r => r.Path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))) { try { var assembly = Assembly.ReflectionOnlyLoadFrom(reference.Path); _registeredNamespaces.AddRange(assembly.GetCustomAttributesData() .Where(attr => attr.AttributeType.Name == "XmlnsDefinitionAttribute" && attr.ConstructorArguments[0].Value.Equals(alias)) .Select(attr => Tuple.Create(attr.ConstructorArguments[1].Value.ToString(), assembly))); } catch {} } } public string ResolveTypeFullName(string localTagName) { return _registeredNamespaces.Select(i => i.Item2.GetType(i.Item1 + "." + localTagName)).First(i => i != null).FullName; } }
public Dictionary<string, ITypeResolver> TypeResolvers(XmlDocument xmlDocument) { var resolvers = new Dictionary<string, ITypeResolver>(); var namespaces = xmlDocument.SelectNodes("//namespace::*").OfType<XmlNode>().Distinct().ToArray(); foreach (var nmsp in namespaces) { var match = Regex.Match(string.Format("{0}=\"{1}\"", nmsp.Name, nmsp.Value), @"xmlns:(?<prefix>\w*)=""((clr-namespace:(?<namespace>[\w.]*))|([^""]))*"""); var namespaceGroup = match.Groups["namespace"]; var prefix = match.Groups["prefix"].Value; if (string.IsNullOrEmpty(prefix)) prefix = ""; if (resolvers.ContainsKey(prefix)) continue; if (namespaceGroup != null && namespaceGroup.Success) { // namespace resolvers.Add(prefix, new ExplicitNamespaceResolver(namespaceGroup.Value)); } else { //Alias XmlnsDefinitionAttribute resolvers.Add(prefix, new XmlnsAliasResolver(VSProject, nmsp.Value)); } } return resolvers; }
public Resource[] ResourcesFromFile(string filename) { var xmlDocument = new XmlDocument(); xmlDocument.Load(Path.GetDirectoryName(VSProject.Project.FileName) + filename); var typeResolvers = TypeResolvers(xmlDocument); var nsmgr = new XmlNamespaceManager(xmlDocument.NameTable); nsmgr.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml"); var resourceNodes = xmlDocument.SelectNodes("//*[@x:Key]", nsmgr).OfType<XmlNode>().ToArray(); var result = new List<Resource>(); foreach (var resourceNode in resourceNodes) { var prefix = GetPrefix(resourceNode.Name); var localName = GetLocalName(resourceNode.Name); var resourceName = resourceNode.SelectSingleNode("./@x:Key", nsmgr).Value; result.Add(new Resource(resourceName, typeResolvers[prefix].ResolveTypeFullName(localName))); } return result.ToArray(); }
public struct Resource { public string Key { get; private set; } public string Type { get; private set; } public Resource(string key, string type) : this() { Key = key; Type = type; } }
public void OutputPropery(Resource resource) { #> private static bool _<#=resource.Key #>IsLoaded; private static <#=resource.Type #> _<#=resource.Key #>; public static <#=resource.Type #> <#=resource.Key #> { get { if (!_<#=resource.Key #>IsLoaded) { _<#=resource.Key #> = (<#=resource.Type #>)Application.Current.Resources["<#=resource.Key #>"]; _<#=resource.Key #>IsLoaded = true; } return _<#=resource.Key #>; } } <#+ }
<#@ template debug="false" hostSpecific="true" language="C#" #> <#@ assembly name="System.Windows" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Linq" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Xml" #> <#@ assembly name="System.Xml.Linq" #> <#@ assembly name="EnvDTE" #> <#@ assembly name="VSLangProj" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Reflection" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.Xml" #> <#@ import namespace="System.Text.RegularExpressions" #> <#@ import namespace="VSLangProj" #> <#@ output extension=".cs" #> using System.Windows; namespace <#=ProjectDefaultNamespace#> { public static class AppResourcess { <# foreach (var resource in ResourcesFromFile("/App.xaml")) { OutputPropery(resource); } #> } } <#+ public void OutputPropery(Resource resource) { #> private static bool _<#=resource.Key #>IsLoaded; private static <#=resource.Type #> _<#=resource.Key #>; public static <#=resource.Type #> <#=resource.Key #> { get { if (!_<#=resource.Key #>IsLoaded) { _<#=resource.Key #> = (<#=resource.Type #>)Application.Current.Resources["<#=resource.Key #>"]; _<#=resource.Key #>IsLoaded = true; } return _<#=resource.Key #>; } } <#+ } private VSProject _vsProject; public VSProject VSProject { get { if (_vsProject == null) { var serviceProvider = (IServiceProvider) Host; var dte = (DTE)serviceProvider.GetService(typeof (DTE)); _vsProject = (VSProject)dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject.Object; } return _vsProject; } } private string _projectDefaultNamespace; public string ProjectDefaultNamespace { get { if (_projectDefaultNamespace == null) _projectDefaultNamespace = VSProject.Project.Properties.Item("DefaultNamespace").Value.ToString(); return _projectDefaultNamespace; } } public struct Resource { public string Key { get; private set; } public string Type { get; private set; } public Resource(string key, string type) : this() { Key = key; Type = type; } } public Resource[] ResourcesFromFile(string filename) { var xmlDocument = new XmlDocument(); xmlDocument.Load(Path.GetDirectoryName(VSProject.Project.FileName) + filename); var typeResolvers = TypeResolvers(xmlDocument); var nsmgr = new XmlNamespaceManager(xmlDocument.NameTable); nsmgr.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml"); var resourceNodes = xmlDocument.SelectNodes("//*[@x:Key]", nsmgr).OfType<XmlNode>().ToArray(); var result = new List<Resource>(); foreach (var resourceNode in resourceNodes) { var prefix = GetPrefix(resourceNode.Name); var localName = GetLocalName(resourceNode.Name); var resourceName = resourceNode.SelectSingleNode("./@x:Key", nsmgr).Value; result.Add(new Resource(resourceName, typeResolvers[prefix].ResolveTypeFullName(localName))); } return result.ToArray(); } public Dictionary<string, ITypeResolver> TypeResolvers(XmlDocument xmlDocument) { var resolvers = new Dictionary<string, ITypeResolver>(); var namespaces = xmlDocument.SelectNodes("//namespace::*").OfType<XmlNode>().Distinct().ToArray(); foreach (var nmsp in namespaces) { var match = Regex.Match(string.Format("{0}=\"{1}\"", nmsp.Name, nmsp.Value), @"xmlns:(?<prefix>\w*)=""((clr-namespace:(?<namespace>[\w.]*))|([^""]))*"""); var namespaceGroup = match.Groups["namespace"]; var prefix = match.Groups["prefix"].Value; if (string.IsNullOrEmpty(prefix)) prefix = ""; if (resolvers.ContainsKey(prefix)) continue; if (namespaceGroup != null && namespaceGroup.Success) { // namespace resolvers.Add(prefix, new ExplicitNamespaceResolver(namespaceGroup.Value)); } else { //Alias XmlnsDefinitionAttribute resolvers.Add(prefix, new XmlnsAliasResolver(VSProject, nmsp.Value)); } } return resolvers; } public interface ITypeResolver { string ResolveTypeFullName(string localTagName); } public class ExplicitNamespaceResolver : ITypeResolver { private string _singleNamespace; public ExplicitNamespaceResolver(string singleNamespace) { _singleNamespace = singleNamespace; } public string ResolveTypeFullName(string localTagName) { return _singleNamespace + "." + localTagName; } } public class XmlnsAliasResolver : ITypeResolver { private readonly List<Tuple<string, Assembly>> _registeredNamespaces = new List<Tuple<string, Assembly>>(); public XmlnsAliasResolver(VSProject project, string alias) { foreach (var reference in project.References.OfType<Reference>() .Where(r => r.Path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))) { try { var assembly = Assembly.ReflectionOnlyLoadFrom(reference.Path); _registeredNamespaces.AddRange(assembly.GetCustomAttributesData() .Where(attr => attr.AttributeType.Name == "XmlnsDefinitionAttribute" && attr.ConstructorArguments[0].Value.Equals(alias)) .Select(attr => Tuple.Create(attr.ConstructorArguments[1].Value.ToString(), assembly))); } catch {} } } public string ResolveTypeFullName(string localTagName) { return _registeredNamespaces.Select(i => i.Item2.GetType(i.Item1 + "." + localTagName)).First(i => i != null).FullName; } } string GetPrefix(string xamlTag) { if (string.IsNullOrEmpty(xamlTag)) throw new ArgumentException("xamlTag is null or empty", "xamlTag"); var strings = xamlTag.Split(new[] {":"}, StringSplitOptions.RemoveEmptyEntries); if(strings.Length <2) return ""; return strings[0]; } string GetLocalName(string xamlTag) { if (string.IsNullOrEmpty(xamlTag)) throw new ArgumentException("xamlTag is null or empty", "xamlTag"); var strings = xamlTag.Split(new[] {":"}, StringSplitOptions.RemoveEmptyEntries); if(strings.Length <2) return xamlTag; return strings[1]; } #>
Source: https://habr.com/ru/post/249105/
All Articles