在Orchard CMS的官网已经提供了文档说明如何打包,但是如果使用它的打包方式,打好的nuget包是带源代码的。如果是为开源系统写模块,不需要关注源代码是否可见。但是如果是用Orchard CMS作为商业用途,那么可能你需要阅读这边文章啦。
1.获取打包文件的原理:
简单说一下Orchard打包模块获取需要打包的文件的原理:控制台传入模块名称,通过找到对应模块的.csproj来分析需要打包的文件,每个.csproj中的ItemGroup节点下的文件就是需要打包的文件
所有的文件名和地址都封装成为IPackageFile,
最终使用NuGet的打包管理工具进行打包。
Orchard默认提供的打包程序都会把源代码打入包内,有时候我们需要不带源代码的NuGet包,所以就需要把Orchard.Package模块的PackageBuilder类改造一下下。
class="line-number" rel="file-gistfile1-cs-L1">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
public class PackageBuilder : IPackageBuilder { private readonly IWebSiteFolder _webSiteFolder; private readonly IVirtualPathProvider _virtualPathProvider; private readonly IOrchardFrameworkAssemblies _frameworkAssemblies; private static readonly string[] _ignoredThemeExtensions = new[] { "obj", "pdb", "exclude" }; private static readonly string[] _ignoredThemePaths = new[] { "/obj/" }; private static bool IgnoreFile(string filePath) { return String.IsNullOrEmpty(filePath) || _ignoredThemePaths.Any(filePath.Contains) || _ignoredThemeExtensions.Contains(Path.GetExtension(filePath) ?? ""); } public PackageBuilder(IWebSiteFolder webSiteFolder, IVirtualPathProvider virtualPathProvider, IOrchardFrameworkAssemblies frameworkAssemblies) { _webSiteFolder = webSiteFolder; _virtualPathProvider = virtualPathProvider; _frameworkAssemblies = frameworkAssemblies; } public Stream BuildPackage(ExtensionDescriptor extensionDescriptor) { var context = new CreateContext(); BeginPackage(context); try { EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Id, extensionDescriptor.ExtensionType); SetCoreProperties(context, extensionDescriptor); string projectFile = extensionDescriptor.Id + ".csproj"; string assemblyFile = string.Format("bin/{0}.dll", extensionDescriptor.Id); if (LoadProject(context, projectFile)) { EmbedVirtualFile(context, assemblyFile, MediaTypeNames.Application.Octet); EmbedProjectFiles(context, "Content", "None", "EmbeddedResource"); EmbedReferenceFiles(context); } else if (DefaultExtensionTypes.IsTheme(extensionDescriptor.ExtensionType)) { // this is a simple theme with no csproj EmbedThemeFiles(context); } } finally { EndPackage(context); } if (context.Stream.CanSeek) { context.Stream.Seek(0, SeekOrigin.Begin); } return context.Stream; } public static string BuildPackageId(string extensionName, string extensionType) { return PackagingSourceManager.GetExtensionPrefix(extensionType) + extensionName; } private static void SetCoreProperties(CreateContext context, ExtensionDescriptor extensionDescriptor) { context.Builder.Id = BuildPackageId(extensionDescriptor.Id, extensionDescriptor.ExtensionType); context.Builder.Version = new Version(extensionDescriptor.Version); context.Builder.Title = extensionDescriptor.Name ?? extensionDescriptor.Id; context.Builder.Description = extensionDescriptor.Description; context.Builder.Authors.Add(extensionDescriptor.Author); if(Uri.IsWellFormedUriString(extensionDescriptor.WebSite, UriKind.Absolute)) { context.Builder.ProjectUrl = new Uri(extensionDescriptor.WebSite); } } private static void EmbedProjectFiles(CreateContext context, params string[] itemGroupTypes) { IEnumerable<XElement> itemGroups = context.Project .Elements(Ns("Project")) .Elements(Ns("ItemGroup")); foreach (string itemGroupType in itemGroupTypes) { IEnumerable<string> includePaths = itemGroups .Elements(Ns(itemGroupType)) .Attributes("Include") .Select(x => x.Value); foreach (string includePath in includePaths) { EmbedVirtualFile(context, includePath, MediaTypeNames.Application.Octet); } } } private void EmbedReferenceFiles(CreateContext context) { var entries = context.Project .Elements(Ns("Project")) .Elements(Ns("ItemGroup")) .Elements(Ns("Reference")) .Select(reference => new { Include = reference.Attribute("Include"), HintPath = reference.Element(Ns("HintPath")) }) .Where(entry => entry.Include != null); foreach (var entry in entries) { var assemblyName = new AssemblyName(entry.Include.Value); // If it is not a core assembly if (_frameworkAssemblies.GetFrameworkAssemblies().FirstOrDefault(assembly => assembly.Name.Equals(assemblyName.Name)) == null) { string virtualPath = _virtualPathProvider.GetReferenceVirtualPath(context.SourcePath, assemblyName.Name, entry.HintPath != null ? entry.HintPath.Value : null); if (!string.IsNullOrEmpty(virtualPath)) { EmbedVirtualFile(context, virtualPath, MediaTypeNames.Application.Octet); } } } } private static void EmbedThemeFiles(CreateContext context) { var basePath = context.SourcePath; foreach (var virtualPath in context.SourceFolder.ListFiles(context.SourcePath, true)) { // ignore dlls, etc if (IgnoreFile(virtualPath)) { continue; } // full virtual path given but we need the relative path so it can be put into // the package that way (the package itself is the logical base path). // Get it by stripping the basePath off including the slash. var relativePath = virtualPath.Replace(basePath, ""); EmbedVirtualFile(context, relativePath, MediaTypeNames.Application.Octet); } } private static XName Ns(string localName) { return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003"); } private static void BeginPackage(CreateContext context) { context.Stream = new MemoryStream(); context.Builder = new NuGetPackageBuilder(); } private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName, string moduleType) { context.SourceFolder = webSiteFolder; if (DefaultExtensionTypes.IsTheme(moduleType)) { context.SourcePath = "~/Themes/" + moduleName + "/"; context.TargetPath = "\\Content\\Themes\\" + moduleName + "\\"; } else { context.SourcePath = "~/Modules/" + moduleName + "/"; context.TargetPath = "\\Content\\Modules\\" + moduleName + "\\"; } } private static bool LoadProject(CreateContext context, string relativePath) { string virtualPath = context.SourcePath + relativePath; if (context.SourceFolder.FileExists(virtualPath)) { context.Project = XDocument.Parse(context.SourceFolder.ReadFile(context.SourcePath + relativePath)); return true; } return false; } private static void EmbedVirtualFile(CreateContext context, string relativePath, string contentType) { var file = new VirtualPackageFile( context.SourceFolder, context.SourcePath + relativePath, context.TargetPath + relativePath); context.Builder.Files.Add(file); } private static void EndPackage(CreateContext context) { context.Builder.Save(context.Stream); } #region Nested type: CreateContext private class CreateContext { public Stream Stream { get; set; } public NuGetPackageBuilder Builder { get; set; } public IWebSiteFolder SourceFolder { get; set; } public string SourcePath { get; set; } public string TargetPath { get; set; } public XDocument Project { get; set; } } #endregion #region Nested type: CreateContext private class VirtualPackageFile : IPackageFile { private readonly IWebSiteFolder _webSiteFolder; private readonly string _virtualPath; private readonly string _packagePath; public VirtualPackageFile(IWebSiteFolder webSiteFolder, string virtualPath, string packagePath) { _webSiteFolder = webSiteFolder; _virtualPath = virtualPath; _packagePath = packagePath; } public string Path { get { return _packagePath; } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Supposed to return an open stream.")] public Stream GetStream() { var stream = new MemoryStream(); _webSiteFolder.CopyFileTo(_virtualPath, stream); stream.Seek(0, SeekOrigin.Begin); return stream; } } #endregion }view raw gistfile1.cs hosted with ? by GitHub
如果你是使用Orchard源码,那么你直接把上面的类覆盖到你的PackageBuilder类即可(一会儿会说明如何使用模块管理功能来更新打包功能)。
编译后就可以享受不带源码的模块打包啦。
如果你的项目中直接用的Orchard.Web,没有使用源码编译,那么没关系,你只需要到下面的地址下载dll,替换到你的modules文件夹下的Orchard.Package的bin中的Orchard.Package.dll即可。
https://github.com/nicholaspei/Orchard.PackageAssembly/blob/master/assembly/Orchard.Packaging.zip