<#@ template hostspecific="true" #> <#@ assembly name="EnvDTE" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Windows.Forms" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.ComponentModel.Design" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Resources" #> <#@ import namespace="System.Text.RegularExpressions" #> <#@ import namespace="EnvDTE" #> <# var model = LoadResources(); #> // using System; using System.Reflection; using System.Resources; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; namespace <#= model.Namespace #> { /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// <#= model.AccessModifier #> static class <#= model.Class #> { private static readonly ResourceManager _resourceManager = new ResourceManager("<#= model.ResourceName #>", typeof(<#= model.Class #>).GetTypeInfo().Assembly); <# foreach (var resource in model.Resources) { #> /// <# foreach (var line in Lines(resource.Value)) { #> /// <#= Xml(line) #> <# } #> /// <# if (resource.ForLogging) { if (resource.Types.Count() > 6) { #> public static readonly FallbackEventDefinition <#= resource.Name #> = new FallbackEventDefinition( <#= resource.EventId #>, LogLevel.<#= resource.Level #>, _resourceManager.GetString("<#= resource.Name #>")); <# } else { var genericTypes = resource.Types.Any() ? ("<" + List(resource.Types) + ">") : ""; #> public static readonly EventDefinition<#= genericTypes #> <#= resource.Name #> = new EventDefinition<#= genericTypes #>( <#= resource.EventId #>, LogLevel.<#= resource.Level #>, LoggerMessage.Define<#= genericTypes #>( LogLevel.<#= resource.Level #>, <#= resource.EventId #>, _resourceManager.GetString("<#= resource.Name #>"))); <# } } else { if (resource.Parameters.Any()) { #> public static string <#= resource.Name #>(<#= List("[CanBeNull] object ", resource.Parameters) #>) => string.Format( GetString("<#= resource.Name #>", <#= List("nameof(", resource.Parameters, ")") #>), <#= List(resource.Parameters) #>); <# } else { #> public static string <#= resource.Name #> => GetString("<#= resource.Name #>"); <# } } } #> private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); for (var i = 0; i < formatterNames.Length; i++) { value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); } return value; } } } <#+ ResourceFile LoadResources() { var result = new ResourceFile(); if (Session.ContainsKey("AccessModifier")) { result.AccessModifier = (string)Session["AccessModifier"]; }; var services = (IServiceProvider)Host; var dte = (DTE)services.GetService(typeof(DTE)); var resourceFile = (string)Session["ResourceFile"]; if (!Path.IsPathRooted(resourceFile)) { resourceFile = Host.ResolvePath(resourceFile); } var resourceProjectItem = dte.Solution.FindProjectItem(resourceFile); var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile); var project = templateProjectItem.ContainingProject; var rootNamespace = (string)project.Properties.Item("RootNamespace").Value; var resourceDir = Path.GetDirectoryName(resourceFile); var projectDir = (string)project.Properties.Item("FullPath").Value; var resourceNamespace = rootNamespace + "." + resourceDir.Substring(projectDir.Length) .Replace(Path.DirectorySeparatorChar, '.'); result.Namespace = (string)resourceProjectItem.Properties.Item("CustomToolNamespace")?.Value; if (string.IsNullOrEmpty(result.Namespace)) { result.Namespace = resourceNamespace; } result.Class = Path.GetFileNameWithoutExtension(resourceFile); result.ResourceName = resourceNamespace + "." + result.Class; using (var reader = new ResXResourceReader(resourceFile)) { reader.UseResXDataNodes = true; result.Resources = Enumerable.ToList( from DictionaryEntry r in reader select new Resource((ResXDataNode)r.Value)); } return result; } IEnumerable Lines(string value) => value.Split(new[] { Environment.NewLine }, StringSplitOptions.None); string Xml(string value) => value.Replace("<", "<").Replace(">", ">"); string List(IEnumerable items) => List(null, items); string List(string prefix, IEnumerable items, string suffix = null) => string.Join(", ", items.Select(i => prefix + i + suffix)); class ResourceFile { public string Namespace { get; set; } public string AccessModifier { get; set; } = "public"; public string Class { get; set; } public string ResourceName { get; set; } public IEnumerable Resources { get; set; } } class Resource { public Resource(ResXDataNode node) { Name = node.Name; Value = (string)node.GetValue((ITypeResolutionService)null); Parameters = Regex.Matches(Value, @"\{(\w+)\}") .Cast() .Select(m => m.Groups[1].Value) .Distinct() .ToList(); var eventInfo = node.Comment.Split(' '); Level = eventInfo.FirstOrDefault() ?? "BadLevel"; EventId = eventInfo.Skip(1).FirstOrDefault() ?? "BadEventId"; Types = eventInfo.Skip(2).ToList(); } public string Name { get; } public string Value { get; } public string EventId { get; } public string Level { get; } public bool ForLogging => Name.StartsWith("Log"); public IEnumerable Parameters { get; } public IEnumerable Types { get; } } #>