在Orchard CMS的官网已经提供了文档说明如何打包,但是如果使用它的打包方式,打好的nuget包是带源代码的。如果是为开源系统写模块,不需要关注源代码是否可见。但是如果是用Orchard CMS作为商业用途,那么可能你需要阅读这边文章啦。
1.获取打包文件的原理:
简单说一下Orchard打包模块获取需要打包的文件的原理:控制台传入模块名称,通过找到对应模块的.csproj来分析需要打包的文件,每个.csproj中的ItemGroup节点下的文件就是需要打包的文件
所有的文件名和地址都封装成为IPackageFile,
最终使用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
}
|
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
}
|
如果你是使用Orchard源码,那么你直接把上面的类覆盖到你的PackageBuilder类即可(一会儿会说明如何使用模块管理功能来更新打包功能)。
编译后就可以享受不带源码的模块打包啦。
如果你的项目中直接用的Orchard.Web,没有使用源码编译,那么没关系,你只需要到下面的地址下载dll,替换到你的modules文件夹下的Orchard.Package的bin中的Orchard.Package.dll即可。
https://github.com/nicholaspei/Orchard.PackageAssembly/blob/master/assembly/Orchard.Packaging.zip