![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
MVCScaffolding
Установим T4Scaffolding: PM> Install-Package T4Scaffolding Создадим папку CodeTemplates/Scaffolders/IRepository в LessonProject.Model в ней добавим файлы IRepository.ps1 (LessonProject.Model/CodeTemplates/Scaffolders/IRepository/IRepository.ps1): [T4Scaffolding.Scaffolder(Description = " Create IRepository interface")][CmdletBinding()] param( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$ModelType, [string]$Project, [string]$CodeLanguage, [string[]]$TemplateFolders, [switch]$Force = $false )
$foundModelType = Get-ProjectType $ModelType -Project $Project -BlockUi if (! $foundModelType) { return }
# Find the IRepository interface, or create it via a template if not already present $foundIRepositoryType = Get-ProjectType IRepository -Project $Project -AllowMultiple if(! $foundIRepositoryType) { #Create IRepository $outputPath = " IRepository" $defaultNamespace = (Get-Project $Project).Properties.Item(" DefaultNamespace").Value
Add-ProjectItemViaTemplate $outputPath -Template IRepositoryTemplate ` -Model @{ Namespace = $defaultNamespace } ` -SuccessMessage " Added IRepository at {0}" ` -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force: $Force
$foundIRepositoryType = Get-ProjectType IRepository -Project $Project }
# Add a new property on the DbContext class if ($foundIRepositoryType) { $propertyName = $foundModelType.Name $propertyNames = Get-PluralizedWord $propertyName # This *is* a DbContext, so we can freely add a new property if there isn't already one for this model Add-ClassMemberViaTemplate -Name $propertyName -CodeClass $foundIRepositoryType -Template IRepositoryItemTemplate -Model @{ EntityType = $foundModelType; EntityTypeNamePluralized = $propertyNames; } -SuccessMessage " Added '$propertyName' to interface '$($foundIRepositoryType.FullName)'" -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage
}
return @{ DbContextType = $foundDbContextType } Потом IRepositoryItemTemplate.cs.t4: < #@ Template Language=" C#" HostSpecific=" True" Inherits=" DynamicTransform" #> #region < #= ((EnvDTE.CodeType)Model.EntityType).Name #>
IQueryable< < #= ((EnvDTE.CodeType)Model.EntityType).Name #> > < #= Model.EntityTypeNamePluralized #> { get; }
bool Create< #= ((EnvDTE.CodeType)Model.EntityType).Name #> (< #= ((EnvDTE.CodeType)Model.EntityType).Name #> instance);
bool Update< #= ((EnvDTE.CodeType)Model.EntityType).Name #> (< #= ((EnvDTE.CodeType)Model.EntityType).Name #> instance);
bool Remove< #=((EnvDTE.CodeType)Model.EntityType).Name #> (int id< #= ((EnvDTE.CodeType)Model.EntityType).Name #>);
#endregion И IRepositoryTemplate.cs.t4: < #@ Template Language=" C#" HostSpecific=" True" Inherits=" DynamicTransform" #> < #@ Output Extension=" cs" #> using System; using System.Collections.Generic; using System.Linq; using System.Web;
namespace < #= Model.Namespace #> { public interface IRepository { IQueryable< T> GetTable< T> () where T: class; } }
Создадим новую таблицу Notify:
Перенесем в DbContext (LessonProjectDb.dbml) и сохраняем (ctrl-S): В Package Manager Console пишем для проекта LessonProject.Model: PM> Scaffold IRepository Notify Added 'Notify' to interface 'LessonProject.Model.IRepository' Ура! Всё работает! Просто, не правда ли? Ничего не ясно? Ок, ладно разберем IRepository.ps1 по порядку: [T4Scaffolding.Scaffolder(Description = " Create IRepository interface")][CmdletBinding()] param( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string ]$ModelType, [string]$Project, [string]$CodeLanguage, [string[]]$TemplateFolders, [switch]$Force = $false )
Это структура объявления кода скаффолдера. Особое внимание нужно обратить на $ModelType – это имя класса, именно его мы и передаем в команде Scaffold IRepository Notify. Остальные параметры идут или по умолчанию, как Force, или по умолчанию известны, как Project, CodeLanguage. Далее мы ищем этот класс (если мы не сохранимся, то искомый класс еще не будет записан и не будет найден): $foundModelType = Get-ProjectType $ModelType -Project $Project -BlockUi if (! $foundModelType) { return }
Класс найден и мы переходим к следующей части. Найти файл IRepository.cs и если его нет, то создать: # Find the IRepository interface, or create it via a template if not already present $foundIRepositoryType = Get-ProjectType IRepository -Project $Project -AllowMultiple if (! $foundIRepositoryType) { #Create IRepository $outputPath = " IRepository" $defaultNamespace = (Get-Project $Project).Properties.Item(" DefaultNamespace").Value
Add-ProjectItemViaTemplate $outputPath -Template IRepositoryTemplate ` -Model @{ Namespace = $defaultNamespace } ` -SuccessMessage " Added IRepository at {0}" ` -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force: $Force
$foundIRepositoryType = Get-ProjectType IRepository -Project $Project }
Тут как раз вызывается IRepositoryTemplate.cs.t4 при необходимости, и туда в качестве модели данных (так же, как в View) передается объект -Model @{ Namespace = $defaultNamespace } `
А defaultNamespace был получен из свойства проекта Get-Project $Project).Properties.Item(" DefaultNamespace").Value
В шаблоне мы это используем (CodeTemplates/Scaffolders/IRepository/IRepositoryTemplate.cs.t4): namespace < #= Model.Namespace #> Ок, файл создан (или найден) и идем к следующему шагу. Если всё хорошо сгеренировалось ($foundIRepositoryType), то добавим в этот класс несколько свойств по шаблону IRepositoryItemTemplate с параметрами:
# Add a new property on the DbContext class if ($foundIRepositoryType) { $propertyName = $foundModelType.Name $propertyNames = Get-PluralizedWord $propertyName # This *is* a DbContext, so we can freely add a new property if there isn't already one for this model Add-ClassMemberViaTemplate -Name $propertyName -CodeClass $foundIRepositoryType -Template IRepositoryItemTemplate -Model @{ EntityType = $foundModelType; EntityTypeNamePluralized = $propertyNames; } -SuccessMessage " Added '$propertyName' to interface '$($foundIRepositoryType.FullName)'" -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage
} Параметры: -Model @{ EntityType = $foundModelType; EntityTypeNamePluralized = $propertyNames; } Кстати, обратите внимание на Get-PluralizedWord и какую роль оно сыграло в созданном шаблоне: IQueryable< Notify> Notifies { get; } Т.е. нормально сформировал множественное число, а не просто прибавлением символа ‘s’, как это было бы в сниппете. Изучим еще эти T4Scaffolding cmdlet: · Add-ClassMember – добавляет кусочек кода в существующий класс: $class = Get-ProjectType HomeController Add-ClassMember $class " public string MyNewStringField; " · Add-ClassMemberViaTemplate – добавляем блок кода через шаблон T4: $class = Get-ProjectType HomeController Add-ClassMemberViaTemplate -CodeClass $class -Template " YourTemplateName" -Model @{ SomeParam = " SomeValue"; AnotherParam = $false } -TemplateFolders $TemplateFolders · Add-ProjectItemViaTemplate – добавляем файл (project item) посредством шаблона: Add-ProjectItemViaTemplate -OutputPath " Some\Folder\MyFile" -Template " YourTemplateName" -Model @{ SomeParam = " SomeValue"; AnotherParam = $false } -TemplateFolders $TemplateFolders · Get-PluralizedWord / Get-SingularizedWord – получаем множественное/единственное число слова: $result = Get-PluralizedWord Person # Sets $result to " People" $result = Get-SingularizedWord People # Sets $result to " Person"
· Get-PrimaryKey – получить первичный ключ из модели данных: $pk = Get-PrimaryKey StockItem · Get-ProjectFolder – получить класс проектной папки $folder = Get-ProjectFolder " Views\Shared" Write-Host " The shared views folder contains $($folder.Count) items" · Get-ProjectItem – получить файл $file = Get-ProjectItem " Controllers\HomeController.cs" $file.Open() $file.Activate() · Get-ProjectLanguage – для C# проектов – возвращает cs, для VB проектов возвращает VB $defaultProjectLanguage = Get-ProjectLanguage $otherProjectLanguage = Get-ProjectLanguage -Project SomeOtherProjectName · Get-ProjectType – получит модель класса (EnvDTE.CodeType) $class = Get-ProjectType HomeController Add-ClassMember $class " public string MyNewStringField; " · Get-RelatedEntities – находит все связанные один-ко-многим объекты класса Get-RelatedEntities Product · Set-IsCheckedOut – это для работы с source-control. Т.е. если надо checkOut файл какой-то, то это можно выполнить этой командой. Set-IsCheckedOut " Controllers\HomeController.cs" Ну что? Чувствуете мощь, которая уже заменит копипастинг в ваших проектах? Но(!) Учтите, что все эти команды были реализованы тоже людьми. И, например, получение первичного ключа будет происходить только, если поле называется ID, а если оно называется PervichniyKlyuch – то, скорее всего, это не сработает. Также сильно не стоит уповать на переводы. Это скаффолдинг, т.е. черновое создание проекта, а не тончайшая настройка. Суть скаффолдинга – это создать, запустить и пойти пить чай, пока программа в автоматическом режиме сделает за вас самую противную механическую рутину.
|