Orchard CMS中如何打包不带源码的模块

Orchard CMS中如何打包不带源码的模块

在Orchard CMS的官网已经提供了文档说明如何打包,但是如果使用它的打包方式,打好的nuget包是带源代码的。如果是为开源系统写模块,不需要关注源代码是否可见。但是如果是用Orchard CMS作为商业用途,那么可能你需要阅读这边文章啦。

1.获取打包文件的原理:

简单说一下Orchard打包模块获取需要打包的文件的原理:控制台传入模块名称,通过找到对应模块的.csproj来分析需要打包的文件,每个.csproj中的ItemGroup节点下的文件就是需要打包的文件

image

所有的文件名和地址都封装成为IPackageFile,

image

最终使用NuGet的打包管理工具进行打包。

Orchard默认提供的打包程序都会把源代码打入包内,有时候我们需要不带源代码的NuGet包,所以就需要把Orchard.Package模块的PackageBuilder类改造一下下。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
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 rawgistfile1.cs hosted with ❤ by GitHub
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
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 rawgistfile1.cs hosted with ❤ by GitHub

如果你是使用Orchard源码,那么你直接把上面的类覆盖到你的PackageBuilder类即可(一会儿会说明如何使用模块管理功能来更新打包功能)。

image 

编译后就可以享受不带源码的模块打包啦。

如果你的项目中直接用的Orchard.Web,没有使用源码编译,那么没关系,你只需要到下面的地址下载dll,替换到你的modules文件夹下的Orchard.Package的bin中的Orchard.Package.dll即可。

https://github.com/nicholaspei/Orchard.PackageAssembly/blob/master/assembly/Orchard.Packaging.zip

原文地址:https://www.cnblogs.com/Leo_wl/p/3413337.html