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 raw gistfile1.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 raw gistfile1.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

你可能感兴趣的:(char)