在【Xamarin+Prism開發(fā)詳解系列】里面經(jīng)常使用到【Prism unity app】的模板創(chuàng)建Prism.Forms項目:
備注:由于Unity社區(qū)已經(jīng)不怎么活躍,下一個版本將會有Autofac,DryIOC,Ninject的項目模板。
自動彈出選擇框:
對于我這類還沒有動手寫過模板的人來說,確實挺新奇的。于是就決定自己也寫個類似的試試,目的就是通過向導創(chuàng)建跨平臺Plugin項目,類似Plugin for xamarin,不過是針對Prism,對應平臺可以自由選擇創(chuàng)建。試了之后才發(fā)現(xiàn)也有不少注意的地方,特寫下此文做備忘。
項目地址:https://github.com/NewBLife/Prism.Forms.Plugin
插件下載地址:TemplatesForPrism.vsix
1、安裝插件開發(fā)用的Extensibility模板與工具
2、新建VSIX Project插件項目
source.extension.vsixmanifest 這個文件相當重要,里面可以指定安裝目標,模板,向導等。
最后我實現(xiàn)的例子:
安裝目標:VS2013以上(2017估計不行)
資產(chǎn):Project模板,Item模板,Wizard向導
3、從【C# Item Template】與【C# Project Template】模板創(chuàng)建項目。
4、從【類庫】模板創(chuàng)建Wizard項目。(Wizard向導只能是類庫)
以上步驟之后的項目結構:
介紹:
Prism.Forms.Plugin.Nuspec:Plugin打包文件模板
Prism.Forms.Plugin:Plugin項目模板
Prism.Forms.Plugin.Wizard:Plugin創(chuàng)建向導
TemplatesForPrism:VSIX插件項目
5、添加引用
Prism.Forms.Plugin.Nuspec:Microsoft.VisaulStudio.CoreUtility
Prism.Forms.Plugin:Microsoft.VisaulStudio.CoreUtility
Prism.Forms.Plugin.Wizard:Microsoft.VisaulStudio.TemplateWizardinterface,envdte
TemplatesForPrism:Prism.Forms.Plugin.Nuspec,Prism.Forms.Plugin,Prism.Forms.Plugin.Wizard
6、添加生成向導
6.1、NewProjectWizard項目選擇向導創(chuàng)建新建一個WinForm選擇框,返回選擇的結果。
繼承IWiazrd向導接口實現(xiàn):
using EnvDTE;using Microsoft.VisualStudio.TemplateWizard;using System;using System.Collections.Generic;using System.IO;namespace Prism.Forms.Plugin.Wizard { public class NewProjectWizard : IWizard { private DTE _dte = null; private string _solutionDir = null; private string _templateDir = null; private string _projectName = null; PluginNewProjectDialogResult _dialogResult; public void BeforeOpeningFile(ProjectItem projectItem) { } public void ProjectFinishedGenerating(Project project) {if
(_dialogResult.CreateAndroid) CreateProject(Target.Droid.ToString()); if (_dialogResult.CreateiOS) CreateProject(Target.iOS.ToString()); if
(_dialogResult.CreateUwp) CreateProject(Target.UWP.ToString()); }
void CreateProject(string platform) { string name = $"{_projectName}.{platform}"; string projectPath =System.IO.Path.Combine(_solutionDir, Path.Combine(_projectName, name)); string templateName = $"Prism.Forms.Plugin.{platform}"; string templatePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(_templateDir), $"{templateName}.zip\\{templateName}.vstemplate"
); _dte.Solution.AddFromTemplate(templatePath, projectPath, name); } public void ProjectItemFinishedGenerating(ProjectItem projectItem) { } public void RunFinished() { } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { try { _dte = automationObject as DTE; _projectName = replacementsDictionary["$safeprojectname$"]; _solutionDir = System.IO.Path.GetDirectoryName(replacementsDictionary["$destinationdirectory$"]); _templateDir = System.IO.Path.GetDirectoryName(customParams[0] as string); PluginNewProjectDialog dialog
= new PluginNewProjectDialog(); dialog.ShowDialog(); _dialogResult =
dialog.Result; if (_dialogResult.Cancelled) throw new WizardBackoutException(); } catch (Exception) { if (Directory.Exists(_solutionDir)) Directory.Delete(_solutionDir, true); throw; } } public bool ShouldAddProjectItem(string filePath) { return true; } } }
模板選擇后執(zhí)行RunStarted==》彈出Winform選擇框==》執(zhí)行ProjectFinishedGenerating創(chuàng)建子項目
6.2、項目名稱safeprojectgroupname向導創(chuàng)建
在NewProjectWizard向導的CreateProject方法里面我們設置了每個子項目的名稱為"{_projectName}.{platform}",所以到達子項目的時候$safeprojectname$里面已經(jīng)帶了iOS,Droid,UWP等名稱,所以有必要進行處理。
using EnvDTE;using Microsoft.VisualStudio.TemplateWizard;using System.Collections.Generic;using System.Threading;namespace Prism.Forms.Plugin.Wizard { public class SafeProjectGroupName : IWizard { public const string ParameterName = "$safeprojectgroupname$"; static ThreadLocal<string> projectGroupName = new ThreadLocal<string>(); bool isRootWizard; public void BeforeOpeningFile(ProjectItem projectItem) { } public void ProjectFinishedGenerating(Project project) { } public void ProjectItemFinishedGenerating(ProjectItem projectItem) { } public void RunFinished() { // If we were the ones to set the value, we must clear it. if (isRootWizard) projectGroupName.Value = null; } public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { if (projectGroupName.Value == null) { var name = replacementsDictionary["$safeprojectname$"]; if (name.EndsWith(Target.Abstractions.ToString())) { projectGroupName.Value = name.Replace($".{Target.Abstractions.ToString()}", string.Empty); } else if (name.EndsWith(Target.Droid.ToString())) { projectGroupName.Value = name.Replace($".{Target.Droid.ToString()}", string.Empty); } else if (name.EndsWith(Target.iOS.ToString())) { projectGroupName.Value = name.Replace($".{Target.iOS.ToString()}", string.Empty); } else if (name.EndsWith(Target.UWP.ToString())) { projectGroupName.Value = name.Replace($".{Target.UWP.ToString()}", string.Empty); } // If there wasn't a value already, it means we're the root wizard itself. isRootWizard = true; } replacementsDictionary[ParameterName] = projectGroupName.Value; } public bool ShouldAddProjectItem(string filePath) { return true; } } }
Debug測試方法:
給類庫添加署名,否則無法注冊
管理員權限啟動VS2015 開發(fā)人員命令提示工具
導航到wizard生成目錄
執(zhí)行gacutil -if Prism.Forms.Plugin.Wizard.dll 命令注冊類庫
執(zhí)行gacutil –l 列出類庫的Token信息(Prism.Forms.Plugin.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b2335488e79a16da, processorArchitecture=MSIL)
模板文件的WizarExtension節(jié)點添加以上Token信息與入口類名稱
安裝模板,設置斷點
啟動另一個Visual Studio程序
調試-》附加到進程-》附加新啟動的Visual Studio進程
新Visual Studio窗口選擇建立的模板,將進入斷點
7、添加模板文件并設置
Prism.Forms.Plugin.Nuspec模板設置
<?xml version="1.0" encoding="utf-8"?> <VSTemplate Version="3.0.0" Type="Item" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010"> <TemplateData> <Name>Plugin nuspec for Prism.Forms</Name> <Description>Create a nuspec file for Prism.Forms.Plugin solution</Description> <Icon>Prism.Forms.Plugin.Nuspec.ico</Icon> <TemplateID>325a0391-d11c-4432-8658-b70405881e87</TemplateID>
<ProjectType>General</ProjectType>
<RequiredFrameworkVersion>2.0</RequiredFrameworkVersion> <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp> <DefaultName>PrismFormsPlugin.nuspec</DefaultName> </TemplateData> <TemplateContent> <ProjectItem TargetFileName="$fileinputname$.nuspec" ReplaceParameters="true">Prism.Forms.Plugin.nuspec</ProjectItem> </TemplateContent> </VSTemplate>
注意點:
Item模板的ProjectType默認為CSharp,有時候沒法找到,最好設置為General。
模板參照文件的生成操作都設置為無。
記得設置分類Category,這樣好找。
效果如下:(在添加新項里面)
Prism.Forms.Plugin模板設置
每個文件夾下面為相應的模板文件
Prism.Forms.Plugin.Abstractions:接口定義
Prism.Forms.Plugin.Droid:Android平臺特性的接口實現(xiàn)
Prism.Forms.Plugin.iOS:iOS平臺特性的接口實現(xiàn)
Prism.Forms.Plugin.UWP:UWP平臺特性的接口實現(xiàn)
最外面的入口模板文件Prism.Forms.Plugin.vstemplate設置:
<?xml version="1.0" encoding="utf-8"?> <VSTemplate Version="3.0.0"
Type="ProjectGroup"
xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010"> <TemplateData> <Name>Plugin for Prism.Forms</Name> <Description>Creates all files necessary to create a plugin for Prism.Forms</Description> <Icon>Prism.Forms.Plugin.ico</Icon> <ProjectType>CSharp</ProjectType> <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion> <SortOrder>30</SortOrder> <TemplateID>16bac5e1-199d-4e08-9ed3-2ef287221be1</TemplateID> <DefaultName>PrismFormsPlugin</DefaultName> <ProvideDefaultName>true</ProvideDefaultName> <PromptForSaveOnCreation>true</PromptForSaveOnCreation> <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp> </TemplateData> <TemplateContent>
<ProjectCollection> <ProjectTemplateLink ProjectName="$safeprojectname$.Abstractions">
Prism.Forms.Plugin.Abstractions\Prism.Forms.Plugin.Abstractions.vstemplate
</ProjectTemplateLink> </ProjectCollection>
</TemplateContent>
<WizardExtension> <Assembly>Prism.Forms.Plugin.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b2335488e79a16da</Assembly> <FullClassName>Prism.Forms.Plugin.Wizard.NewProjectWizard</FullClassName> </WizardExtension>
</VSTemplate>
注意點:
入口模板文件的Type必須為ProjectGroup,否則只創(chuàng)建一個工程項目
模板內(nèi)容必須使用ProjectTemplateLink添加每個子項目的模板文件設置
由于使用向導可選擇方式創(chuàng)建子項目,所有這里只添加了接口的模板文件
WizarExtension節(jié)點為向導程序設置,調用Prism.Forms.Plugin.Wizard.NewProjectWizard
子項目模板Prism.Forms.Plugin.Abstractions.vstemplate設置:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"
http://www.cnblogs.com/lixiaobin/p/VSIX.html