Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / WinForms, .Net Framework |
![]() ![]() |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
Кажется в VS2017 EnvDTE игнорирует атрибуты. Пример: namespace ConsoleApp2 { [Test] class Program { static void Main(string[] args) { } } class Test : Attribute { } } Добавляю в приложение шаблон Template1.tt: <#@ template debug="true" hostSpecific="true" #> <#@ output extension=".txt" #> <#@ Assembly Name="System.Core" #> <#@ import namespace="System" #> <#@ import namespace="System.Collections.Generic" #> <#@ assembly name="EnvDTE" #> <#@ import namespace="EnvDTE" #> <# Init(); WriteLine(Classes.Count.ToString()); //попытка получить атрибуты: foreach(CodeClass cc in Classes) { foreach(CodeElement ce in cc.Members){ if(ce.Kind == vsCMElement.vsCMElementFunction){ CodeFunction cf = ce as CodeFunction; WriteLine(ce.Name + " " + cf.Attributes.Count.ToString()); } } } #> <#+ public CodeNamespace Ns {get;set;} public List<CodeClass> Classes {get;set;} public void Init(){ IServiceProvider hostServiceProvider = (IServiceProvider)Host; DTE dte = (DTE)hostServiceProvider.GetService(typeof(DTE)); Project proj=null; foreach(Project p in dte.Solution.Projects){ if(p.Name == "ConsoleApp2"){ proj=p; break; } } foreach(CodeElement ce in proj.CodeModel.CodeElements) { if(ce.Name=="ConsoleApp2"){ Ns = ce as CodeNamespace; break; } } Classes = new List<CodeClass>(); GetClasses(Ns); } public void GetClasses(CodeNamespace cn){ foreach(CodeElement ce in cn.Members) { if(ce.Kind == vsCMElement.vsCMElementNamespace) { GetClasses(ce as CodeNamespace); } else if(ce.Kind == vsCMElement.vsCMElementClass) { Classes.Add(ce as CodeClass); } } } #>на выходе: 2 Main 0Это у всех так или только у меня? Или я не там ищу атрибут Test? |
18 май 17, 19:42 [20494027] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
В примере косяк, [Test] у Main должен стоять. |
18 май 17, 19:53 [20494064] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
Блин, пример заработал. |
18 май 17, 20:12 [20494099] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
А вот в пустом проекте типа WebApplication не пашут атрибуты в шаблончеге. |
18 май 17, 20:23 [20494126] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
Не пашут лишь у методов контроллеров. Вот гадство, именно там они и нужны. |
19 май 17, 10:23 [20495170] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
<#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>
|
||
19 май 17, 10:36 [20495242] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
* Скомпилируй сборку и работай ... |
19 май 17, 10:37 [20495247] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
В общем, достоверно обнаружил, что атрибуты не видны, если файл с исходником не в корне проекта, а в папке. Двойное гадство. |
||
19 май 17, 11:09 [20495449] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
|
||||
19 май 17, 11:10 [20495459] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
Рефлекшн обломался:Ошибка Выполнение преобразования: System.IO.FileNotFoundException: Не удалось загрузить файл или сборку "System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" либо одну из их зависимостей. Не удается найти указанный файл. |
19 май 17, 11:34 [20495581] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
У меня это, так же, работает для анализа классов MVC/WebAPI конроллеров, проблем нет. Гружу сборку через: var controllersAssembly = Path.Combine(ProjectFolder, "Bin", Path.ChangeExtension(ProjectName, "dll")); Assembly.LoadFrom(controllersAssembly);
|
|
19 май 17, 11:43 [20495632] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
Добавлю, работаю с VS2013, MVC5. Про заморочки с другими версиями не в курсе. |
19 май 17, 11:48 [20495656] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
С рефлекшеном проблемы начинаются тут: foreach(var t in Assembly.LoadFrom(controllersAssembly).ExportedTypes) А с DTE - гемор с атрибутами. Попробуй мой шаблон у себя запустить, только замени "ConsoleApp2" на имя своего проекта и корневого неймспейса. У меня сейчас нет другой студии, а тип приложения пофиг. Я в консольном закинул Program.cs в папку, и атрибуты стали невидимы. |
||
19 май 17, 12:07 [20495754] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
<#+ class Controller { public string VarName; public string Path; public string[] Actions; } enum ControllersTypes { Mvc, Api } const string S_Controller = "Controller"; const string S_MvcController = "System.Web.Mvc.Controller"; const string S_ApiController = "System.Web.Http.ApiController"; Controller[] GetControllers() { var assembly = Assembly.LoadFrom(ControllersAssembly); var q = from t in assembly.GetTypes() let ctt = GetControllerType(t) where ctt.HasValue let ct = CreateController(t, ctt.Value) orderby ct.VarName select ct; return q.ToArray(); } Controller CreateController(Type type, ControllersTypes controllerType) { var name = type.Name.Substring(0, type.Name.Length - S_Controller.Length); return new Controller { VarName = name, Path = GetControllerPath(name, controllerType), Actions = GetControllerActions(type) }; } ControllersTypes? GetControllerType(Type type) { if (type.Name.EndsWith(S_Controller) == false) return null; if (HasBaseType(type, S_MvcController)) return ControllersTypes.Mvc; if (HasBaseType(type, S_ApiController)) return ControllersTypes.Api; return null; } bool HasBaseType(Type type, string typeName) { while (true) { type = type.BaseType; if (type == null) break; if (type.FullName == typeName) return true; } return false; } string GetControllerPath(string name, ControllersTypes controllerType) { if (controllerType == ControllersTypes.Mvc) return name; if (controllerType == ControllersTypes.Api) return "api/" + name; throw new ArgumentException("type"); } string[] GetControllerActions(Type type) { var q = from t in GetControllerActionsTypes(type) from m in t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) where m.IsSpecialName == false select m.Name; return q.Distinct().OrderBy(n => n).ToArray(); } IEnumerable<Type> GetControllerActionsTypes(Type type) { while (true) { yield return type; type = type.BaseType; if (type == null || type.FullName == S_MvcController || type.FullName == S_ApiController) break; } } #> |
||||
19 май 17, 13:13 [20496183] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
Antonariy, а вообще, может через Roslyn попробовать? Его изобрели вроде как как раз для этого. |
19 май 17, 13:20 [20496245] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
assembly.GetTypes() - не удается загрузить один или более запрошенных типов. |
19 май 17, 13:22 [20496256] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
|
||
19 май 17, 13:24 [20496267] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
|
||||
19 май 17, 13:30 [20496313] Ответить | Цитировать Сообщить модератору |
Алексей К Member Откуда: Новосибирск Сообщений: 13578 |
|
||
19 май 17, 13:33 [20496327] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
|
||||
19 май 17, 13:50 [20496392] Ответить | Цитировать Сообщить модератору |
Antonariy Member Откуда: ☭ Сообщений: 73366 |
А текст можно и через dte анализировать, или вообще без ничего. но это костыль. Уж лучше в названия методов добавлять префиксы/постфиксы вместо атрибутов. |
||||
19 май 17, 14:03 [20496460] Ответить | Цитировать Сообщить модератору |
Все форумы / WinForms, .Net Framework | ![]() |