Created
May 17, 2014 11:39
-
-
Save urasandesu/4f99747caea265a579ec to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CmdletBinding()] | |
param ( | |
[string[]] | |
$ReferenceFrom, | |
[string] | |
$Assembly, | |
[string] | |
$TargetFrameworkVersion, | |
[string] | |
$KeyFile, | |
[string] | |
$OutputPath, | |
[string] | |
$Settings, | |
[switch] | |
$WhatIf | |
) | |
# ----------------------------------------------------------------------------------------------- | |
# | |
# Utilities | |
# | |
# ----------------------------------------------------------------------------------------------- | |
$ToRootNamespace = { | |
param ($AssemblyInfo) | |
$AssemblyInfo.GetName().Name + '.Prig' | |
} | |
$ToSignAssembly = { | |
param ($KeyFile) | |
if ([string]::IsNullOrEmpty($KeyFile)) { | |
$false | |
} else { | |
$true | |
} | |
} | |
$ToProcessorArchitectureConstant = { | |
param ($AssemblyInfo) | |
switch ($AssemblyInfo.GetName().ProcessorArchitecture) | |
{ | |
'X86' { "_M_IX86" } | |
'Amd64' { "_M_AMD64" } | |
'MSIL' { "_M_MSIL" } | |
Default { "_M_MSIL" } | |
} | |
} | |
$ToTargetFrameworkVersionConstant = { | |
param ($TargetFrameworkVersion) | |
switch ($TargetFrameworkVersion) | |
{ | |
'v3.5' { "_NET_3_5" } | |
'v4.0' { "_NET_4" } | |
'v4.5' { "_NET_4_5" } | |
'v4.5.1' { "_NET_4_5_1" } | |
Default { "_NET_4" } | |
} | |
} | |
$ToDefineConstants = { | |
param ($AssemblyInfo, $TargetFrameworkVersion) | |
$result = (& $ToProcessorArchitectureConstant $AssemblyInfo), (& $ToTargetFrameworkVersionConstant $TargetFrameworkVersion) | |
$result -join ';' | |
} | |
$ToPlatformTarget = { | |
param ($AssemblyInfo) | |
switch ($AssemblyInfo.GetName().ProcessorArchitecture) | |
{ | |
'X86' { "x86" } | |
'Amd64' { "x64" } | |
'MSIL' { "AnyCPU" } | |
Default { "AnyCPU" } | |
} | |
} | |
$ToProcessorArchitectureString = { | |
param ($AssemblyInfo) | |
switch ($AssemblyInfo.GetName().ProcessorArchitecture) | |
{ | |
'X86' { "x86" } | |
'Amd64' { "AMD64" } | |
'MSIL' { "MSIL" } | |
Default { "MSIL" } | |
} | |
} | |
$ToAssemblyName = { | |
param ($AssemblyInfo) | |
'{0}.{1}.v{2}.{3}.Prig' -f $AssemblyInfo.GetName().Name, $AssemblyInfo.ImageRuntimeVersion, $AssemblyInfo.GetName().Version.ToString(), (& $ToProcessorArchitectureString $AssemblyInfo) | |
} | |
$ToReferenceInclude = { | |
param ($refAsmInfos) | |
foreach ($refAsmInfo in $refAsmInfos) { | |
@" | |
<Reference Include="$($refAsmInfo.GetName().Name)"> | |
<HintPath>$($refAsmInfo.Location)</HintPath> | |
</Reference> | |
"@ | |
} | |
} | |
$GenerateCsproj = { | |
param ($AssemblyInfo, $ReferencedAssemblyInfos, $KeyFile, $TargetFrameworkVersion, $OutputPath) | |
$rootNamespace = & $ToRootNamespace $AssemblyInfo | |
$signAsm = & $ToSignAssembly $KeyFile | |
$defineConsts = & $ToDefineConstants $AssemblyInfo $TargetFrameworkVersion | |
$platform = & $ToPlatformTarget $AssemblyInfo | |
$asmName = & $ToAssemblyName $AssemblyInfo | |
$refInc = & $ToReferenceInclude $ReferencedAssemblyInfos | |
$csprojTemplate = [xml]@" | |
<?xml version="1.0" encoding="utf-8"?> | |
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
<PropertyGroup> | |
<OutputType>Library</OutputType> | |
<RootNamespace>$rootNamespace</RootNamespace> | |
<FileAlignment>512</FileAlignment> | |
<SignAssembly>$signAsm</SignAssembly> | |
<AssemblyOriginatorKeyFile>$KeyFile</AssemblyOriginatorKeyFile> | |
<OutputPath>$OutputPath</OutputPath> | |
<DefineConstants>$defineConsts</DefineConstants> | |
<PlatformTarget>$platform</PlatformTarget> | |
<DebugType>pdbonly</DebugType> | |
<Optimize>true</Optimize> | |
<TargetFrameworkVersion>$TargetFrameworkVersion</TargetFrameworkVersion> | |
<AssemblyName>$asmName</AssemblyName> | |
</PropertyGroup> | |
<ItemGroup>$refInc</ItemGroup> | |
<ItemGroup> | |
<Compile Include="**/*.cs" /> | |
</ItemGroup> | |
<Import Project="`$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |
</Project> | |
"@ | |
New-Object psobject | | |
Add-Member NoteProperty 'Path' "$rootNamespace.csproj" -PassThru | | |
Add-Member NoteProperty 'XmlDocument' $csprojTemplate -PassThru | |
} | |
$ToFullNameFromType = { | |
param ($Type) | |
$defName = $Type.FullName | |
if ($Type.IsGenericType -and !$Type.IsGenericTypeDefinition) | |
{ | |
$defName = $Type.Namespace + "." + $Type.Name | |
} elseif ($Type.ContainsGenericParameters) { | |
$defName = $Type.Name | |
} | |
if ($Type.IsGenericType) { | |
$defName = $defName -replace '`\d+', '' | |
$genericArgNames = @() | |
foreach ($genericArg in $Type.GetGenericArguments()) { | |
$genericArgNames += (& $ToFullNameFromType $genericArg) | |
} | |
$defName = ($defName + "<" + ($genericArgNames -join ', ') + ">") | |
} | |
$defName | |
} | |
$ToClassNameFromType = { | |
param ($Type) | |
$defName = $Type.Name | |
if ($Type.IsGenericType) { | |
$defName = $defName -replace '`\d+', '' | |
$genericArgNames = @() | |
foreach ($genericArg in $Type.GetGenericArguments()) { | |
$genericArgNames += (& $ToFullNameFromType $genericArg) | |
} | |
$defName = ($defName + "<" + ($genericArgNames -join ', ') + ">") | |
} | |
$defName | |
} | |
$ToClassNameFromStub = { | |
param ($Stub) | |
$defName = $Stub.Alias | |
if ($Stub.Target.IsGenericMethod) { | |
$defName = $defName -replace '`\d+', '' | |
$genericArgNames = @() | |
foreach ($genericArg in $Stub.Target.GetGenericArguments()) { | |
$genericArgNames += (& $ToFullNameFromType $genericArg) | |
} | |
$defName = ($defName + "<" + ($genericArgNames -join ', ') + ">") | |
} | |
$defName | |
} | |
$GenerateTokensCs = { | |
param ($AssemblyInfo, $Section, $TargetFrameworkVersion) | |
$content = @" | |
#if $(& $ToTargetFrameworkVersionConstant $TargetFrameworkVersion) && $(& $ToProcessorArchitectureConstant $AssemblyInfo) | |
//------------------------------------------------------------------------------ | |
// <auto-generated> | |
// This code was generated by a tool. | |
// Assembly : $($AssemblyInfo.GetName().Name) | |
// Runtime Version : $($AssemblyInfo.ImageRuntimeVersion) | |
// Assembly Version : $($AssemblyInfo.GetName().Version.ToString()) | |
// Processor Architecture : $(& $ToProcessorArchitectureString $AssemblyInfo) | |
// | |
// Changes to this file may cause incorrect behavior and will be lost if | |
// the code is regenerated. | |
// </auto-generated> | |
//------------------------------------------------------------------------------ | |
using Urasandesu.Prig.Framework; | |
"@ + $(foreach ($stub in $Section.Stubs) { | |
@" | |
[assembly: Indirectable($($stub.Target.DeclaringType.Namespace).Prig.P$($stub.Target.DeclaringType.Name).TokenOf$($stub.Name))] | |
"@}) + @" | |
"@ + $(foreach ($namespaceGrouped in $Section.GroupedStubs) { | |
@" | |
namespace $($namespaceGrouped.Key).Prig | |
{ | |
"@ + $(foreach ($declTypeGrouped in $namespaceGrouped) { | |
@" | |
public partial class P$(& $ToClassNameFromType $declTypeGrouped.Key) | |
{ | |
"@ + $(foreach ($stub in $declTypeGrouped) { | |
@" | |
internal const int TokenOf$($stub.Name) = 0x$($stub.Target.MetadataToken.ToString('X8')); | |
"@}) + @" | |
} | |
"@}) + @" | |
} | |
"@}) + @" | |
#endif | |
"@ | |
New-Object psobject | | |
Add-Member NoteProperty 'Path' 'AutoGen\Tokens.g.cs' -PassThru | | |
Add-Member NoteProperty 'Content' $content -PassThru | |
} | |
$GenerateStubsCs = { | |
param ($AssemblyInfo, $Section, $TargetFrameworkVersion) | |
$results = New-Object System.Collections.ArrayList | |
foreach ($namespaceGrouped in $Section.GroupedStubs) { | |
$dir = $namespaceGrouped.Key -replace '\.', '\' | |
foreach ($declTypeGrouped in $namespaceGrouped) { | |
$content = @" | |
using Urasandesu.Prig.Framework; | |
namespace $($namespaceGrouped.Key).Prig | |
{ | |
public partial class P$(& $ToClassNameFromType $declTypeGrouped.Key) | |
{ | |
"@ + $(foreach ($stub in $declTypeGrouped) { | |
@" | |
public static class $(& $ToClassNameFromStub $stub) | |
{ | |
public static $(& $ToClassNameFromType $stub.IndirectionDelegate) Body | |
{ | |
set | |
{ | |
var info = new IndirectionInfo(); | |
info.AssemblyName = "$($AssemblyInfo.FullName)"; | |
info.Token = TokenOf$($stub.Name); | |
var holder = LooseCrossDomainAccessor.GetOrRegister<IndirectionHolder<$(& $ToClassNameFromType $stub.IndirectionDelegate)>>(); | |
holder.AddOrUpdate(info, value); | |
} | |
} | |
} | |
"@}) + @" | |
} | |
} | |
"@ | |
$result = | |
New-Object psobject | | |
Add-Member NoteProperty 'Path' "$dir\$($declTypeGrouped.Key.Name).cs" -PassThru | | |
Add-Member NoteProperty 'Content' $content -PassThru | |
[Void]$results.Add($result) | |
} | |
} | |
,$results | |
} | |
# ----------------------------------------------------------------------------------------------- | |
# | |
# Main | |
# | |
# ----------------------------------------------------------------------------------------------- | |
Write-Verbose ('ReferenceFrom : {0}' -f $ReferenceFrom) | |
Write-Verbose ('Assembly : {0}' -f $Assembly) | |
Write-Verbose ('Target Framework Version : {0}' -f $TargetFrameworkVersion) | |
Write-Verbose ('Key File : {0}' -f $KeyFile) | |
Write-Verbose ('Output Path : {0}' -f $OutputPath) | |
Write-Verbose ('Settings : {0}' -f $Settings) | |
Write-Verbose 'Load Settings ...' | |
[Void][System.Reflection.Assembly]::LoadWithPartialName('System.Configuration') | |
$asmInfo = [System.Reflection.Assembly]::Load($Assembly) | |
$refAsmInfos = New-Object 'System.Collections.Generic.List[System.Reflection.Assembly]' | |
foreach ($refFrom in $ReferenceFrom) { | |
$refAsmInfos.Add([System.Reflection.Assembly]::LoadFrom($refFrom)) | |
} | |
$onAsmInfoResolve = [System.ResolveEventHandler] { | |
param($Sender, $E) | |
foreach($curAsmInfo in [System.AppDomain]::CurrentDomain.GetAssemblies()) { | |
if ($curAsmInfo.FullName -match $E.Name) { | |
return $curAsmInfo | |
} | |
} | |
return $null | |
} | |
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAsmInfoResolve) | |
$fileMap = New-Object System.Configuration.ExeConfigurationFileMap | |
$fileMap.ExeConfigFilename = $Settings | |
$config = [System.Configuration.ConfigurationManager]::OpenMappedExeConfiguration($fileMap, [System.Configuration.ConfigurationUserLevel]::None) | |
$section = $config.GetSection("prig") | |
Write-Verbose 'Generate Tokens.g.cs ...' | |
$tokensCsInfo = & $GenerateTokensCs $asmInfo $section $TargetFrameworkVersion | |
$tokensCsDir = [System.IO.Path]::GetDirectoryName($tokensCsInfo.Path) | |
if (![string]::IsNullOrEmpty($tokensCsDir) -and ![IO.Directory]::Exists($tokensCsDir)) { | |
New-Item $tokensCsDir -ItemType Directory -WhatIf:$WhatIf -ErrorAction Stop | Out-Null | |
} | |
$tokensCsInfo.Content | Out-File $tokensCsInfo.Path -Encoding utf8 -WhatIf:$WhatIf -ErrorAction Stop | Out-Null | |
Write-Verbose 'Generate stubs *.cs ...' | |
$stubsCsInfos = & $GenerateStubsCs $asmInfo $section $TargetFrameworkVersion | |
foreach ($stubsCsInfo in $stubsCsInfos) { | |
$stubsCsDir = [System.IO.Path]::GetDirectoryName($stubsCsInfo.Path) | |
if (![string]::IsNullOrEmpty($stubsCsDir) -and ![IO.Directory]::Exists($stubsCsDir)) { | |
New-Item $stubsCsDir -ItemType Directory -WhatIf:$WhatIf -ErrorAction Stop | Out-Null | |
} | |
$stubsCsInfo.Content | Out-File $stubsCsInfo.Path -Encoding utf8 -WhatIf:$WhatIf -ErrorAction Stop | Out-Null | |
} | |
Write-Verbose 'Generate *.csproj ...' | |
$csprojInfo = & $GenerateCsproj $asmInfo $refAsmInfos $KeyFile $TargetFrameworkVersion $OutputPath | |
$csprojDir = [System.IO.Path]::GetDirectoryName($csprojInfo.Path) | |
if (![string]::IsNullOrEmpty($csprojDir) -and ![IO.Directory]::Exists($csprojDir)) { | |
New-Item $csprojDir -ItemType Directory -WhatIf:$WhatIf -ErrorAction Stop | Out-Null | |
} | |
$csprojInfo.XmlDocument.Save($csprojInfo.Path) | |
Write-Verbose 'Build all *.cs files ...' | |
& msbuild $csprojInfo.Path /t:rebuild |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment