Visual Studio 15 SP 1
Очередной моментик в Студии...
Пользую шаблоны Т4... не все устраивает, но - работает... по крайней мере это выглядит проще, чем сборка sql-строки в коде метода...
Моментик об котором хочу написать следующий:
- у Студии, в свойствах файла, есть метод (Build Action) обработки соответствующего файла - от ничего до включения ресурсом.
- шаблоны Т4, по умолчанию, включаются как ресурс.
- генетируемый Студией на основе шаблона класс - нормально компилируется.
Потребовалось мне несколько шаблонов исключить из билда. Привычно поставил свойства шаблона в "none" и ожидал, что генерируемый файлик будет исключен из компиляции.
Не сработало!
Т.е. шаблон лежит в проекте с указанием ничего с ним не делать, а сгенерированный (генерируется при сохранении) на его основе (*.cs) файлик - продолжает компилироваться как ни в чем не бывало...
Еще моментик - после возвращения шаблона в обычный (ресурс) режим оказалось, что пропал установленный Custom Tools Namespace. Это не перепроверял, но споткнулся об отсутствие подставляемых параметров в тех шаблонах, которые переводил в "none".
Нашел еще одну веселую штучку. (пишу руками - могут быть ошибки)
interface IFilename
{
String RootPath { get; set; }
String Basename { get; set; }
}
public abstract partial class TBase : IFilename
{
public void Generate()
{
String filename = TFileManager.BuildFilename(this);
....
}
....
String IFilename.RootPath { get; set; }
String IFilename.Basename { get; set; }
}
class MyTemplate : TBase, IFilename
{
public MyTemplate()
{
RootPath = @"c:\_Generated";
Basename = @"MyDoc.dat";
}
String RootPath { get; set; }
String Basename { get; set; }
}
public static class TFileManager
{
public static String BuildFilename(IFilename pFilename)
{
....
}
}
Как помнится, утверждалось, что при наличии двух определений интерфейсов в конечную реализацию входит последняя.
В данном случае последняя реализация находится в классе MyTemplate - там где происходит декларирование полей и присвоение значений.
Однако при кастинге в передаче параметра - в TFileManager.BuildFilename(this); - эта имплементация не используется, а получается первичная из TBase. А там, естественно, все нулл-нулл.
То, что поправить не сложно - понятно, но все же Я получил доступ к не последней реализации интерфейса...
Еще один глюк Студии.
Сейчас вышел SP2. Довольно объемная штучка.
В процессе исталяции можно много чего поменять в настройках.
У меня, в частности, нет необходимости в Win10 SDK.
Глюк в том. что, не смотря на снятие галочки, данный SDK все одно ставится...
Остальное - не отслеживал, но, думаю, что мои настройки почти полностью игнорируются.
Да, кто там бился за Pyton'а? Добавили его для комплекта...
Добавил пару толоозок для работы с шаблонами - 'T4Toolbox' & 'tangible T4'.
По ощущениям - стало существенно медленнее. Особенно чувствуется на загрузке.
У меня SSD и в обычном варианте все летает. Сейчас, при загрузке, весьма тяжко.
Есть и положительные изменения - появилась подсветка синтаксиса в шаблонах
и возможность работать с параметрами в Свойствах. От последнего толку пока
мало - шаблоны получают параметры из сессии, которая лежит в АппХосте и
которую Я на сейчас не использую. генерируемый для параметров код так же
привязан к использованию АппХоста... но тут его можно подменить.
Слепил псевдосессию и передал через нее параметры. Код стал выглядеть/...
хммм... интересно:
TParams param = Load(fi); // загрузка файла с определениями
// установка параметров
TExecutionContext.Instance[Primitive.TNamespaceDefinition.ID] = param.NamespaceDef;
TExecutionContext.Instance[Primitive.TClassDefinition.ID] = param.ClassDef;
//TExecutionContext.Instance[Primitive.TFieldsList.ID] = param.Fields;
TExecutionContext.Instance["Fields"] = param.Fields; // передача - по имени переменной
// инициализация параметров в ДЛЛке
Code.Templates.Base.TBase.ExecutionContext = TExecutionContext.Instance;
Code.Templates.Base.TBase.FileManager = new Code.FileManager.TFileManager();
// генерация - осталось 2 строки на шаблон
TFieldNames fn = new TFieldNames();
//fn.Namespace = param.NamespaceDef;
//fn.Class = param.ClassDef;
//fn.Fields = param.Fields;
fn.Generate();
//generated = fn.TransformText();
//filename = GenerationPath + param.ClassDef.Name + ".FieldNames.cs";
//File.Delete(filename);
//File.AppendAllText(filename, generated);
TRow row = new TRow();
//row.Namespace = param.NamespaceDef;
//row.Class = param.ClassDef;
//row.Fields = param.Fields;
row.Generate();
//generated = row.TransformText();
//filename = GenerationPath + param.ClassDef.Name + ".Row.cs";
//File.Delete(filename);
//File.AppendAllText(filename, generated);
TSubset ss = new TSubset();
//ss.Namespace = param.NamespaceDef;
//ss.Class = param.ClassDef;
//ss.Fields = param.Fields;
ss.Generate();
//generated = ss.TransformText();
//filename = GenerationPath + param.ClassDef.Name + ".Subset.cs";
//File.Delete(filename);
//File.AppendAllText(filename, generated);
TTable tb = new TTable();
//tb.Namespace = param.NamespaceDef;
//tb.Class = param.ClassDef;
//tb.Fields = param.Fields;
tb.Generate();
//generated = tb.TransformText();
//filename = GenerationPath + param.ClassDef.Name + ".Table.cs";
//File.Delete(filename);
//File.AppendAllText(filename, generated);
Но надо дорабатывать - активно использую подшаблоны - туда еще не передаются параметры.
Проблем две - надо научится из конструктора получать ссылку на переменную (ссылку на файл
куда добавлйать текст) с классе которой создается подшаблон и подумать как, через сессию,
передавать параметры при паралельном выполнении кода... НУ да это не сегодня...
P.S. Кто бы мне сказал где поменять код генерируемый для шаблона и параметров... Где
компилятор шаблонов - Я заню, вопрос в том как поменять его выдачу...
Я себе эту штуку установила только потому что там больше готовых "форлагов" для разных проэктов. И именно одно форлаге нужно было для моего проэкта. В остальное я пока не вникала, ибо сама в этом деле - новичек... Мне темы надо одну за другой изучать
Da Ja tozhe ne lezu shibko vpered - 4.0 v samyj raz.
да вы прикалываетесь
в C# наконец-то ввели то, что во всяких пыхпыхах существует 100500 лет
вместо
name = string.Format("Employee name is {0}, located at {1}", emp.FirstName, emp.Location);
можно писать
name = $"Employee name is {emp.FirstName}, located at {emp.Location}";
раньше везде где-нибудь с нумерацией {x} напаришься, вылзит IndexNotBoundException
вместо
string departmentName = emp == null ? null : emp.Department == null ? null : emp.Department.Name;
Теперь:
string departmentName = emp?.Department?.Name;
Неужели так проблемно написать:
name = "Employee name is " + emp.FirstName + ", located at " + emp.Location;
да и работает (вроде) быстрее.
Ну это безотносительно к тому, что в данном случае все форматирование должно быть пропертью/методом объекта emp.
Меня форматирование строк вообще как-то не сильно заботит - для малых объемов - конкатенации достаточно, для больших - есть текстовые шаблоны. Вот сравнение - да, интересует - в плане быстродействия - в три раза по сравнению со стандартным Я поднял, но мало, надо еще разика в три...
Интереснее начинается, когда тебе нужно вытащить время из даты или дробную часть из числа там.
-----
Да ну? Может стоит работу поменять? Ну или инструмент немного подосвоить?
пишут, что конкатенирование это Айайай
-----
Ну пишут и что? Если совсем критично - есть StringBuilder.
Но еще раз повторюсь - у меня нет проблемы с форматированием строки - иногда эта операция не встречается и на 10-ке страниц...
NP.
public class A
{
String _name;
protected A(String pName) { name = pName; }
}
public class B : A
{
protected B(string pName) : base(pName) {}
До этого момента все ясно и понятно
- два класса с защищенными конструкторами - не будут лепится как попало
- один наследуется от другого и может получить доступ к конструктору базового.
public static readonly A Inst = new A("The Name");
}
А вот последняя строка поставила меня в тупик.
Планировалось, что будет вызван конструктор (как любой protected method) базового класса.
Получился, однако, облом - нет доступа к защищенному(!) конструктору... в наследнике.
Что Я там немножко нарушаю парадигму ООП - это понятно.
Просто у меня B очень частный случай А и Я хочу иметь его в топе иерархии.
Ткните, плс, Кота носом в доку, где описано почему недоступен конструктор...
П.С. Поправить - проблемы нет. Хочу понять почему есть ограничение.
Всё элементарно.
Спецификация C# 5.0, §3.4:
all members of the base class, except instance constructors, destructors and static constructors, become members of the derived type
+ §3.5.4
Let B be a base class that declares a protected instance member M, and let D be a class that derives from B. Within the class-body of D, access to M can take one of the following forms:• An unqualified type-name or primary-expression of the form M.• A primary-expression of the form E.M, provided the type of E is T or a class derived from T, where T is the class type D, or a class type constructed from D• A primary-expression of the form base.M.In addition to these forms of access, a derived class can access a protected instance constructor of a base class in a constructor-initializer.
Расшифровывая:
- protected конструктор базового класса не наследуется (отсутствует в наследнике)
- по форме B() из D вызвать нельзя, т.к. такой член в наследнике отсутствует
- по форме E.B() вызвать тоже нельзя, потому что E может быть либо D (что не работает, ибо см. предыдущий пункт), либо наследником D, что также не работает по предыдущим 2 пунктам
- по форме base.B() вызвать тоже нельзя, потому что base.-доступ разрешается только в нестатическом конструкторе, нестатическом методе или нестатическом акцессоре (§7.6.8)
Доступ к protected конструктору базового класса доступен только в инициализаторе нестатического конструктора наследника, что выделено как отдельный пункт в §3.5.4, см выше.
Удалось найти еще один глюк...
Вчера к обеду рубанули электричество... большая часть сделанной за утро работы сохранилась в рековери файлах... что радует...
Однако, без проблем не обошлось.
Найденная проблема - сбросился тип процессора установленный для откладки.
Что огорчает - непонятно как это происходит - Студия до этого выгружалась и загружалась - все было нормально... видимо что-то в процессе восстановления переписывает настройки...
Нашел еще один глюк.
Исходная диспозиция:
- открыто несколько студий
- в студиях открыты разные проекты
- один из проектов - WEB-из-папки
- в WEB-из-папки используется условная компиляция в нескольких страницах (описывал где-то ранее - Global_asax vs Application)
Глюк заключается в том, что если отсутствует хотя бы один из дизайнерских (*,design.vb/*.design.cs), то условная компиляция работает не как определено условиями. Причем результаты условной компиляции становятся непредсказуемыми - где-то правильно, а где-то - как случится. При наличии дизайнерского файла, пусть даже в нем есть ошибки, все выправляется...
Очередные глюки...
Глюк достаточно странный, связан с файлом проекта.
У меня настраиваются три конфигурации: Release, Debug, Tests
Понятно, что по дефаулту их две и третью надо дописывать руками.
За одно с добавлением конфигурации заменяются и пути сброса Длльок.
Рутина.
Глюк первый.
Если не сохранить файл проекта - Студия предложит его сохранить - это нормально,
но после этого Менеджер Конфигураций не видит добавленную конфигурацию, хотя
она есть в файле проекта.
Глюк второй.
При последовательно производится редактирование нескольких файлов проектов.
Если в Менеджере Конфигураций не выбирать нужную конфигурацию, то в какой-то
момент может оказаться, что изменения утрачены. Как - не отследил пока...