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'а? Добавили его для комплекта...
Oracle Developer tool слетел после инсталяции SP2 для Студии...
Добавил пару толоозок для работы с шаблонами - '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. Кто бы мне сказал где поменять код генерируемый для шаблона и параметров... Где
компилятор шаблонов - Я заню, вопрос в том как поменять его выдачу...
Еще одна маленькая бага...
В Шарпе есть возможность определять многострочные сроки.
string myText =
@"Here
is
my
text";
Бага состоит в том, что между @ и кавычками не должно быть пробела.
При пробеле интеллисенсе подчеркивает все красненьким...
Я себе эту штуку установила только потому что там больше готовых "форлагов" для разных проэктов. И именно одно форлаге нужно было для моего проэкта. В остальное я пока не вникала, ибо сама в этом деле - новичек... Мне темы надо одну за другой изучать
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-ке страниц...
Да ну? Может стоит работу поменять? Ну или инструмент немного подосвоить?
а может тебе нахуй пойти?
Вообще-то конкатенация уже давно не айяйяй в шарпах, с рантайма 4.5 компилятор сильно поумнел и делает .Concat() без создания промежуточных строк.
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
Понятно, что по дефаулту их две и третью надо дописывать руками.
За одно с добавлением конфигурации заменяются и пути сброса Длльок.
Рутина.
Глюк первый.
Если не сохранить файл проекта - Студия предложит его сохранить - это нормально,
но после этого Менеджер Конфигураций не видит добавленную конфигурацию, хотя
она есть в файле проекта.
Глюк второй.
При последовательно производится редактирование нескольких файлов проектов.
Если в Менеджере Конфигураций не выбирать нужную конфигурацию, то в какой-то
момент может оказаться, что изменения утрачены. Как - не отследил пока...