ético revista pensamiento para log lecturas horas home gubernamental etica ethos desarrollo certificacion centro cdpe acceso .net visual-studio reflection t4 design-time

.net - pensamiento - lecturas revista ethos gubernamental



Reflejo de tiempo de diseño (3)

La única forma que conozco de hacer esto es utilizar alguna capacidad de análisis de código. No puedo pensar en un camino fuera de mi cabeza cómo hacer eso. Estoy seguro de que .NET tiene algunas utilidades que pueden hacer eso.

No estoy seguro de cuál es su situación, pero generalmente en lugar de leer el código, tiene alguna información centralizada, ya sea un archivo XML o algún diagrama UML (incluso diagrama de clases) que se utiliza para generar código. Simplifica las cosas un poco y hace que sea más fácil hacer cambios y dejar que la generación de código escupir los cambios. Eche un vistazo a las herramientas Tangible T4 para Visual Studio.

¿Hay alguna manera de hacer una precomposición de reflexión, en el momento del diseño?

Mi intención es usar T4 para escupir códigos personalizados basados ​​en clases que implementan ciertas interfaces. Sé que puedo recurrir a la reflexión, pero quiero que el script T4 escupe el código adicional antes de la compilación, de lo contrario necesitaré compilar el código dos veces, una para generar dlls, dos veces para dejar que T4 se refleje en el archivo dll generado anteriormente y agregar andamio adicional.

¿Hay alguna manera de hacer la reflexión en el momento del diseño?

¿Hay una mejor manera de hacer esto?


De hecho, hay una forma de generar código preconstrucción basada en el CodeModel proporcionado por Visual Studio Automation : La interfaz del proyecto proporciona una propiedad "CodeModel" que contiene un gráfico de todos los artefactos del modelo en ese proyecto. Es posible que desee recorrerlo para encontrar clases, interfaces, propiedades, ... en función del cual genere su código de salida.

dandrejw ya mencionó el Tangible T4-Editor . Tiene una galería de plantillas gratis. Existe una plantilla reutilizable, "tangible Visual Studio Automation Helper", que debería ser extremadamente útil en su caso. Usando esta plantilla, puedes resolver tu problema de esta manera:

Este es un código dentro de una plantilla t4 que detecta todas las clases que implementan INotifyPropertyChanged.

<# // get a reference to the project of this t4 template var project = VisualStudioHelper.CurrentProject; // get all class items from the code model var allClasses = VisualStudioHelper.GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false); // iterate all classes foreach(EnvDTE.CodeClass codeClass in allClasses) { // get all interfaces implemented by this class var allInterfaces = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.ImplementedInterfaces, EnvDTE.vsCMElement.vsCMElementInterface, true); if (allInterfaces.OfType<EnvDTE.CodeInterface>() .Any(i => i.Name == "INotifyPropertyChanged")) { #>Render your code here<# } } #>

Coloque su código de salida donde el fragmento de código dice "Renderice su código aquí".


Para los futuros lectores que no estén de humor para intentar que funcione la plantilla T4 VisualStudioHelper, a continuación encontrará una plantilla independiente que enumera todas las clases del proyecto actual. Se probó en Visual Studio 2013 y se inspiró en el código del sitio T4.

<#@ template debug="true" hostSpecific="true" #> <#@ output extension=".cs" #> <#@ Assembly Name="System.Core" #> <#@ assembly name="EnvDte" #> <#@ import namespace="System" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Diagnostics" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <# foreach(var ns in GetNamespaceElements()) { foreach(var cc in ns.Members.OfType<EnvDTE.CodeClass>()) { #>Render your code here<# } } #> <#+ public IEnumerable<EnvDTE.CodeNamespace> GetNamespaceElements() { var visualStudio = (this.Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var project = visualStudio.Solution.FindProjectItem(this.Host.TemplateFile) .ContainingProject as EnvDTE.Project; var projItems = new List<EnvDTE.ProjectItem>(); FillProjectItems(project.ProjectItems, projItems); var names = new HashSet<string>(projItems .Where(i => i.FileCodeModel != null) .SelectMany(i => i.FileCodeModel.CodeElements.OfType<EnvDTE.CodeElement>()) .Where(e => e.Kind == EnvDTE.vsCMElement.vsCMElementNamespace) .Select(e => e.FullName)); var codeNs = new List<EnvDTE.CodeNamespace>(); FillCodeNamespaces(project.CodeModel.CodeElements.OfType<EnvDTE.CodeNamespace>(), codeNs); return codeNs.Where(ns => names.Contains(ns.FullName)); } public void FillCodeNamespaces(IEnumerable<EnvDTE.CodeNamespace> parents, List<EnvDTE.CodeNamespace> all) { foreach (var parent in parents) { all.Add(parent); FillCodeNamespaces(parent.Members.OfType<EnvDTE.CodeNamespace>(), all); } } public void FillProjectItems(EnvDTE.ProjectItems items, List<EnvDTE.ProjectItem> ret) { if (items == null) return; foreach(EnvDTE.ProjectItem item in items) { ret.Add(item); FillProjectItems(item.ProjectItems, ret); } } #>