Notices: This section not yet converted to new layout. Download stats are rolling back out.

CType

1.00.0004

Package test results are passing.

This package was approved by moderator ferventcoder on 5/6/2015.

CType makes it easy to create .NET types, including table formatting and SQL wrappers.

To install CType, run the following command from the command line or from PowerShell:

C:\> choco install ctype

To upgrade CType, run the following command from the command line or from PowerShell:

C:\> choco upgrade ctype

Files

Hide
  • chocolateyInstall.ps1 Show
    $dir = Split-Path -Parent $MyInvocation.MyCommand.Path
    $path = Join-Path $dir 'tools\CType.msi'
    if (Test-Path $path)
    {
        Write-Debug "CType\chocolateyInstall.ps1: $path already present"
    }
    else
    {
        Write-Debug "CType\chocolateyInstall.ps1: $path not already present"
    }
    Write-Debug "CType\chocolateyInstall.ps1: running Install-ChocolateyInstallPackage -PackageName CType -FileType MSI -SilentArgs /Quiet -File $path"
    Install-ChocolateyInstallPackage -PackageName CType -FileType MSI -SilentArgs '/Quiet' -File $path
    Write-Debug "CType\chocolateyInstall.ps1: ran MSI installer"
    
  • chocolateyUninstall.ps1 Show
    $dir = Split-Path -Parent $MyInvocation.MyCommand.Path
    $path = Join-Path $dir 'tools\CType.msi'
    if (Test-Path $path)
    {
        Write-Debug "CType\chocolateyUninstall.ps1: found $path"
    }
    else
    {
        Write-Debug "CType\chocolateyUninstall.ps1: did not find $path"
    }
    
    $env:chocolateyInstallOverride = "true"
    $env:chocolateyInstallArguments = "$path /quiet"
    Write-Debug "The current version of Chocolatey appears to contain a bug in Uninstall-ChocolateyPackage,"
    Write-Debug "where the -File parameter value is ignored when -FileType is MSI."
    Write-Debug "I bypass this by setting"
    Write-Debug '$env:chocolateyInstallOverride = "true"'
    Write-Debug '$env:chocolateyInstallArguments = "$path /quiet"'
    Write-Debug "CType\chocolateyUninstall.ps1: running Uninstall-ChocolateyPackage -PackageName CType -FileType MSI -SilentArgs -File $path"
    
    Write-Debug "CType\chocolateyUninstall.ps1: running Uninstall-ChocolateyPackage -PackageName CType -FileType MSI -SilentArgs /Quiet -File $path"
    Uninstall-ChocolateyPackage -PackageName CType -FileType MSI -SilentArgs '/Quiet' -File $path
    Write-Debug "CType\chocolateyUninstall.ps1: ran MSI uninstaller"
    
  • content\CType\CType.ps1 Show
    # CODEWORK Need better parameter validation
    
    [Hashtable]$CType_AddedTypes = @{}
    
    Write-Verbose 'CType.ps1: adding CType base types'
    Add-Type -ReferencedAssemblies System.Data -TypeDefinition @'
    namespace CType
    {
        public class TypeElement
        {
        }
        public class Property : TypeElement
        {
            public string PropertyName;
            public string PropertyType;
            public string PropertyTableWidth;
            public string[] PropertyKeywords;
        }
        public class Parent : TypeElement
        {
            public string ParentTypeName;
        }
        public class Using : TypeElement
        {
            public string Namespace;
        }
        public class ReferencedAssembly : TypeElement
        {
            public string AssemblyName;
        }
        public class SqlWrapper : TypeElement
        {
        }
        public class SqlTemplateObject : TypeElement
        {
            public System.Data.DataRow DataRow;
        }
        public class NoFormatData : TypeElement
        {
        }
    }
    '@
    
    function Add-CType
    {
    <#
    .SYNOPSIS
    Add a locally-defined type to this runspace.
    
    .DESCRIPTION
    Add a locally-defined type to this runspace, and optionally define table formatting for the type.
    These types can be used as parameter types and in OutputType([typename]) declarations.
    
    .PARAMETER TypeName
    Name for the new type. You can include the namespace here or else specify it separately.
    
    .PARAMETER Namespace
    Namespace containing the new type. If not specified, the namespace is extracted from TypeName.
    
    .PARAMETER ParentTypeName
    Parent class of the new class, default is System.Object
    
    .PARAMETER Using
    Other namespaces, typically those containing types specified in PropertyType
    
    .PARAMETER ReferencedAssemblies
    Other assemblies, typically those containing types specified in PropertyType
    
    .PARAMETER SqlWrapper
    Make the new type a SQL wrapper class for use in ConvertTo-CTypeSqlWrapper.
    This is set automatically if any PropertyKeyword contains SQLWrapper,
    or if SQLTemplateObject is set.
    
    .PARAMETER SqlTemplateObject
    If specified, include all properties of this SQL template object in the SQL wrapper class.
    Properties already specified in PropertyName are not affected.
    SqlWrapper is automatically set if this is specified.
    
    .PARAMETER NoFormatData
    Skip defining formatting metadata for this type.
    For example, you might want to combine all the formatting for the types in your module
    into a single file.
    
    .PARAMETER PropertyName
    Name of a property of the type being defined
    
    .PARAMETER PropertyType
    Type of a property of the type being defined
    
    .PARAMETER PropertyTableWidth
    Table width in characters of a property of the type being defined.
    If one or more properties specify PropertyTableWidth, a formatting directive
    will be generated for this type and entered into the runspace.
    If not specified, this property is not in the default table format.
    This can also be set to '*', in which case this property is displayed at full width;
    this should generally only be used for the last property with defined PropertyTableWidth.
    
    .PARAMETER PropertyKeywords
    Other keywords. The only keywords currently implemented are "Trim"
    which trims leading/trailing whitespace from the output string in the table formatting,
    and "SQLWrapper" which designates a read-only property read from the wrapped SQL object.
    
    .EXAMPLE
    # Define a new type
    PS> @"
    PropertyName,PropertyType,PropertyTableWidth,PropertyKeywords
    PrimaryTarget,string,25,Trim
    SecondaryTarget,string,25,Trim
    Weight,int,10
    IsPrimary,Boolean,10
    Description,String,*
    MainConnection,SqlConnection
    SecondaryConnection,SqlConnection
    "@ | ConvertFrom-Csv | Add-CType -TypeName MyType `
                                     -Namespace MyCompany.Namespace `
                                     -Using System.Data.SqlClient `
                                     -ReferencedAssemblies System.Data
    
    # You can now use this as a full-fledged type, for example define parameters as
    # param( [MyCompany.Namespace.MyType]$MyParameter )
    
    # Create an instance of the type
    PS> New-Object -TypeName MyCompany.Namespace.MyType -Property @{
        PrimaryTarget = "String1";
        SecondaryTarget = "String2";
        Weight = 4;
        Description = "This is a very long description"
        }
    
    PrimaryTarget             SecondaryTarget           Weight     IsPrimary  Description                                                                                                                
    -------------             ---------------           ------     ---------  -----------                                                                                                                
    String1                   String2                   4          False      This is a very long description                                                                                            
    
    .EXAMPLE
    # Define a new CType Class
    ConvertFrom-Csv @'
    PropertyType,PropertyName,PropertyTableWidth,PropertyKeywords
    string,Name,20
    string,HostName,20
    DateTime,WhenCreated,25
    DateTime,WhenDeleted,25
    '@ | Add-CType -TypeName MyCompany.MyNamespace.MyClass
    # Create wrapped object
    New-Object -Type MyCompany.MyNamespace.MyClass -Property @{
        Name = "MyName"
        WhenCreated = (get-date)
    }
    
    .EXAMPLE
    # Define a new SQL Wrapper Class
    ConvertFrom-Csv @'
    PropertyType,PropertyName,PropertyTableWidth,PropertyKeywords
    string,Name,20,SQLWrapper
    string,HostName,20,SQLWrapper
    DateTime,WhenCreated,25,SQLWrapper
    DateTime,WhenDeleted,25,SQLWrapper
    '@ | Add-CType -TypeName MyCompany.MyNamespace.MyClass -SqlWrapper
    # Create wrapped objects
    $SqlWrappedObjects = $SqlDataRows | ConvertTo-CTypeSqlWrapper -TypeName MyCompany.MyNamespace.MyClass
    
    .NOTES
    This method should only be called once for any class. Calling a second time
    is generally harmless as long as the type definition is identical,
    otherwise an error will be reported. Types cannot be altered once added to
    a process (AppDomain?).
    
    .LINK
    ConvertTo-CTypeSqlWrapper
    Add-Type
    Update-CTypeFormatData
    Update-FormatData
    #>
        [CmdletBinding()]
        param(
            [string][parameter(Mandatory=$true)]$TypeName,
            [string]$Namespace,
            [string]$ParentTypeName,
            [string[]]$Using,
            [string[]]$ReferencedAssemblies,
            [switch]$SqlWrapper,
            [System.Data.DataRow]$SqlTemplateObject,
            [switch]$NoFormatData,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyName,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyType,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyTableWidth,
            [string[]][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyKeywords
            )
        begin
        {
    Write-Verbose -Message @"
    $($MyInvocation.InvocationName): TypeName $TypeName
    $($MyInvocation.InvocationName): Namespace $Namespace
    $($MyInvocation.InvocationName): ParentTypeName $ParentTypeName
    $($MyInvocation.InvocationName): Using $Using
    $($MyInvocation.InvocationName): ReferencedAssemblies $ReferencedAssemblies
    $($MyInvocation.InvocationName): SqlWrapper $SqlWrapper
    $($MyInvocation.InvocationName): SqlTemplateObject $SqlTemplateObject
    "@
            if (-not $Namespace)
            {
                $nameComponents = $TypeName.Split('.')
                if ($nameComponents.Count -lt 2)
                {
                    throw 'You must specify a Namespace or else a TypeName which contains a Namespace'
                }
                $TypeName = $nameComponents[-1]
                $Namespace = $nameComponents[0..($nameComponents.Count - 2)] -join '.'
            }
            if ($CType_AddedTypes["$Namespace.$TypeName"])
            {
                Write-Warning "$($MyInvocation.InvocationName): Class $Namespace.$TypeName was already added; trying anyhow"
            }
            if ($SqlTemplateObject)
            {
                $SqlWrapper = $true
            }
            $propertyList = @()
        }
        process
        {
            if ($PropertyName)
            {
    Write-Verbose -Message @"
    $($MyInvocation.InvocationName): PropertyName $PropertyName
    $($MyInvocation.InvocationName): PropertyType $PropertyType
    $($MyInvocation.InvocationName): PropertyTableWidth $PropertyTableWidth
    $($MyInvocation.InvocationName): PropertyKeywords $PropertyKeywords
    "@
                if (-not $PropertyType)
                {
                    throw 'PropertyType must be specified for all properties'
                }
                if ($PropertyTableWidth)
                {
                    if ($PropertyTableWidth -ne '*')
                    {
                        $w = $PropertyTableWidth -as [int]
                        if ($w -lt 1)
                        {
                            throw "PropertyTableWidth must be either a positive integer or '*' if it is specified"
                        }
                    }
                }
                $propertyList += New-Object -TypeName CType.Property -Property @{
                    PropertyName = $PropertyName
                    PropertyType = $PropertyType
                    PropertyTableWidth = $PropertyTableWidth
                    PropertyKeywords = $PropertyKeywords
                    }
                if ('SQLWrapper' -in $PropertyKeywords)
                {
                    $SqlWrapper = $true
                }
            }
        }
        end
        {
            if ($SqlTemplateObject)
            {
                Write-Verbose "$($MyInvocation.InvocationName): SqlTemplateObject specified, adding additional properties"
                foreach ($column in $SqlTemplateObject.Table.Columns)
                {
                    $name = $column.ColumnName
                    $type = $column.DataType
                    if ($name -in $propertyList.PropertyName)
                    {
                        Write-Verbose "$($MyInvocation.InvocationName): SqlTemplateObject column $type $name already in property list"            
                    }
                    else
                    {
                        Write-Verbose "$($MyInvocation.InvocationName): SqlTemplateObject column $type $name must be added property list"            
                        $propertyList += New-Object -TypeName CType.Property -Property @{
                            PropertyName = $name;
                            PropertyType = $type;
                            PropertyTableWidth = 0;
                            PropertyKeywords = @('SQLWrapper');
                            }
                    }
                }
                $SqlWrapper = $true
            }
    
            if ($SqlWrapper)
            {
                if ($Using -notcontains 'System.Data')
                {
                    $Using += 'System.Data'
                }
                if ($ReferencedAssemblies -notcontains 'System.Data')
                {
                    $ReferencedAssemblies += 'System.Data'
                }
            }
    
            Write-Verbose "$($MyInvocation.InvocationName): building C# type definition"
            $typeDefinition = New-Object -TypeName System.Text.StringBuilder
            $Using = @("System") + ($Using | Where-Object {$_})
            $Using | foreach {
                $null = $typeDefinition.AppendLine("using $_;")
                }
    $null = $typeDefinition.AppendLine(@"
    namespace $Namespace
    {
        public class $TypeName $(if ($ParentTypeName) {": $ParentTypeName"})
        {
    "@)
        if ($SqlWrapper)
        {
    $null = $typeDefinition.AppendLine(@"
            private System.Data.DataRow WrappedSqlObject;
    
            public $TypeName(System.Data.DataRow obj)
            {
                this.WrappedSqlObject = obj;
            }
    
    "@)
        }
        foreach ($property in $propertyList)
        {
            $name = $property.PropertyName
            $type = $property.PropertyType
            Write-Verbose "$($MyInvocation.InvocationName) Property $type $name"
    
            # CSharp seems to be picky about spelling and capitalization of these types
            $typeObject = $type -as [Type]
            if ($typeObject.FullName)
            {
                $type = $typeObject.FullName
            }
    
            $propertyType = $type
            if ('SqlWrapper' -in $property.PropertyKeywords)
            {
                $valueExpression = "($type)val";
                if ($typeObject.IsValueType)
                {
                    $propertytype = "Nullable<$type>"
                }
    
    $null = $typeDefinition.AppendLine(@"
            public $propertyType $name
            {
                get {
                    object val = this.WrappedSqlObject["$name"];
                    if ((val == null) || (val.GetType().FullName == "System.DBNull"))
                    {
                        return null;
                    }
                return $valueExpression;
                } // get $propertyType $name
            } // property $propertyType $name
    
    
    "@)
            }
            else # -not $SqlClassWrapper
            {
    
    $null = $typeDefinition.AppendLine(@"
            public $propertyType $name { get; set; }
    "@)
    
            }
        }
    
    $null = $typeDefinition.AppendLine(@"
        }
    }
    "@)
    
            Write-Verbose "$($MyInvocation.InvocationName): Adding type:`n$($typeDefinition.ToString())"
            Add-Type -TypeDefinition $typeDefinition.ToString() -ReferencedAssemblies $ReferencedAssemblies
    
            $CType_AddedTypes["$Namespace.$classname"] = $true
    
            if (-not $NoFormatData)
            {
                $tableProperties = $propertyList | Where-Object {$_.PropertyTableWidth}
                if ($tableProperties)
                {
                    $text = $tableProperties | Get-CTypeFormatPS1XML -TypeName "$Namespace.$TypeName"
                    $text | Update-CTypeFormatData -TypeName "$Namespace.$TypeName"
                }
            }
        }
    }
    
    function Update-CTypeFormatData
    {
    <#
    .SYNOPSIS
    Add the specified formatting metadata to the current runspace.
    
    .PARAMETER TypeName
    Full typename for the type including namespace
    
    .PARAMETER FormatDataString
    Format data string from Get-CTypeFormatPS1XML
    
    .EXAMPLE
    $tableProperties = ConvertFrom-Csv @'
    PropertyType,PropertyName,PropertyTableWidth
    string,Name,20
    string,HostName,20
    DateTime,WhenCreated,25
    DateTime,WhenDeleted,25
    '@
    $text = $tableProperties | Get-CTypeFormatPS1XML -TypeName "$Namespace.$TypeName"
    Update-CTypeFormatData -TypeName "$Namespace.$TypeName" -FormatDataString $text
    
    .LINK
    Get-CTypeFormatPS1XML
    Add-CType
    Update-FormatData
    Update-CTypeTypeData
    #>
        [CmdletBinding()]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName,
            [string][parameter(Mandatory=$true, ValueFromPipeline=$true)]$FormatDataString
            )
        begin
        {
            $activity = "$($MyInvocation.InvocationName) $TypeName"
            $tempfile = Join-Path $env:temp "$TypeName.$(get-date -Format 'yyyyMMdd-hhmmss-fffffff').format.ps1xml"
            [System.Text.StringBuilder]$text = New-Object -TypeName System.Text.StringBuilder
        }
        process
        {
            $null = $text.AppendLine($FormatDataString)
        }
        end
        {
            Write-Verbose "$activity`: Adding format data to temporary file $tempfile from formatting directive:`n$FormatDataString"
            $FormatDataString | Set-Content -Path $tempFile
            try
            {
                Write-Verbose "$activity`: Updating format data"
                Update-FormatData -PrependPath $tempfile
            }
            catch
            {
                if (Test-Path $tempfile -ErrorAction SilentlyContinue)
                {
                    Write-Verbose "$activity`: Deleting temporary file $tempfile"
                    Remove-Item $tempfile
                }
            }
        }
    }
    
    function Update-CTypeTypeData
    {
    <#
    .SYNOPSIS
    Add the specified type metadata to the current runspace.
    
    .PARAMETER TypeName
    Full typename for the type including namespace
    
    .PARAMETER TypeDataString
    Type metadata string
    
    .EXAMPLE
    Update-CTypeTypeData -TypeName "$Namespace.$TypeName" -TypeDataString @"
    <?xml version="1.0" encoding="utf-8" ?>
    <Types>
        <Type>
            <Name>MyCompany.MyNamespace.MyType</Name>
            <Members>
                <MemberSet>
                    <Name>PSStandardMembers</Name>
                    <Members>
                        <NoteProperty>
                            <Name>SerializationDepth</Name>
                            <Value>
                                4
                            </Value>
                        </NoteProperty>
                    </Members>
                </MemberSet>
            </Members>
        </Type>
    </Types>
    "@
    
    .LINK
    Update-CTypeFormatData
    #>
        [CmdletBinding()]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName,
            [string][parameter(Mandatory=$true, ValueFromPipeline=$true)]$TypeDataString
            )
        begin
        {
            $activity = "$($MyInvocation.InvocationName) $TypeName"
            $tempfile = Join-Path $env:temp "$TypeName.$(get-date -Format 'yyyyMMdd-hhmmss-fffffff').format.ps1xml"
            [System.Text.StringBuilder]$text = New-Object -TypeName System.Text.StringBuilder
        }
        process
        {
            $null = $text.AppendLine($TypeDataString)
        }
        end
        {
            Write-Verbose "$activity`: Adding format data to temporary file $tempfile from formatting directive:`n$TypeDataString"
            $TypeDataString | Set-Content -Path $tempFile
            try
            {
                Write-Verbose "$activity`: Updating format data"
                Update-TypeData -PrependPath $tempfile
            }
            catch
            {
                if (Test-Path $tempfile -ErrorAction SilentlyContinue)
                {
                    Write-Verbose "$activity`: Deleting temporary file $tempfile"
                    Remove-Item $tempfile
                }
            }
        }
    }
    
    function Get-CTypeFormatPS1XML
    {
    <#
    .SYNOPSIS
    Returns the text of a PS1XML which defines output formatting for a type.
    
    .DESCRIPTION
    Returns the text of a PS1XML which defines output formatting for a type.
    Pass this to Update-CTypeFormatData to apply this formatting to the current session.
    You can also save this into a PS1XML file associated with your module.
    
    .PARAMETER TypeName
    Name for the type
    
    .PARAMETER PropertyName
    Name of a property of the type being defined
    
    .PARAMETER PropertyType
    Type of a property of the type being defined
    
    .PARAMETER PropertyTableWidth
    Table width of a property of the type being defined, per Add-CType.
    
    .PARAMETER PropertyKeywords
    Other keywords per Add-CType.
    
    .LINK
    Add-CType
    Update-CTypeFormatData
    #>
        [OutputType([string])]
        [CmdletBinding()]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyName,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyType,
            [string][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyTableWidth,
            [string[]][parameter(ValueFromPipelineByPropertyName=$true)]$PropertyKeywords
            )
    
        begin
        {
            $activity = "$($MyInvocation.InvocationName) $TypeName"
            Write-Verbose $activity
    # You could also build this using the [xml] class
    $fileHeader = @"
    <?xml version="1.0" encoding="utf-8" ?>
    <Configuration>
        <ViewDefinitions>
    
    "@
    $templateViewHeader = @"
            <View>
                <Name>{0}</Name>
                <ViewSelectedBy>
                    <TypeName>{0}</TypeName>
                </ViewSelectedBy>
                <TableControl>
                    <TableHeaders>
    "@
    $templateColumnHeader = @"
                        <TableColumnHeader>
                            <Label>{0}</Label>
                        </TableColumnHeader>
    "@
    $templateColumnHeaderWithWidth = @"
                        <TableColumnHeader>
                            <Label>{0}</Label>
                            <Width>{1}</Width>
                        </TableColumnHeader>
    "@
    $headerItemSeparator = @"
                    </TableHeaders>
                    <TableRowEntries>
                        <TableRowEntry>
                            <TableColumnItems>
    "@
    $templateColumnItem = @"
                                <TableColumnItem>
                                    <PropertyName>{0}</PropertyName>
                                </TableColumnItem>
    "@
    $templateColumnItemWithTrim = @"
                                <TableColumnItem>
                                    <ScriptBlock>
                                      (Out-String -InputObject `$_.{0}).Trim()
                                    </ScriptBlock>
                                </TableColumnItem>
    "@
    $viewFooter = @"
                            </TableColumnItems>
                        </TableRowEntry>
                     </TableRowEntries>
                </TableControl>
            </View>        
    "@
    $fileFooter = @"
        </ViewDefinitions>
    </Configuration>
    "@
    
            $propertyList = New-Object System.Collections.ArrayList
    
            $fileContent = New-Object System.Text.StringBuilder -ArgumentList $fileHeader
            $null = $fileContent.AppendLine( ($templateViewHeader -f $TypeName) )
        }
    
        process
        {
    Write-Verbose -Message @"
    $activity`: PropertyName $PropertyName
    $activity`: PropertyType $PropertyType
    $activity`: PropertyTableWidth $PropertyTableWidth
    $activity`: PropertyKeywords $PropertyKeywords
    "@
            if ($PropertyName -and $PropertyTableWidth)
            {
                if (-not $PropertyType)
                {
                    throw 'PropertyType must be specified for all properties'
                }
                if ($PropertyTableWidth)
                {
                    if ($PropertyTableWidth -ne '*')
                    {
                        $w = $PropertyTableWidth -as [int]
                        if ($w -lt 1)
                        {
                            throw "PropertyTableWidth must be either a positive integer or '*' if it is specified"
                        }
                    }
                }
                $obj = New-Object -TypeName CType.Property -Property @{
                    PropertyName = $PropertyName
                    PropertyType = $PropertyType
                    PropertyTableWidth = $PropertyTableWidth
                    PropertyKeywords = $PropertyKeywords
                    }
                $null = $propertyList.Add($obj)
            }
            else
            {
                Write-Verbose "$activity`: Skipping due to null name or width"
            }
        }
    
        end
        {
            foreach ($p in $propertyList)
            {
                if ($p.PropertyTableWidth)
                {
                    if ($p.PropertyTableWidth -eq '*')
                    {
                        $null = $fileContent.AppendLine( ($templateColumnHeader -f $p.PropertyName) )
                    }
                    else
                    {
                        $null = $fileContent.AppendLine( ($templateColumnHeaderWithWidth -f $p.PropertyName,$p.PropertyTableWidth) )
                    }
                }
            }
            $null = $fileContent.AppendLine( $headerItemSeparator )
            foreach ($p in $propertyList)
            {
                if ($p.PropertyTableWidth)
                {
                    if ('Trim' -in $p.PropertyKeywords)
                    {
                        $null = $fileContent.AppendLine( ($templateColumnItemWithTrim -f $p.PropertyName) )
                    }
                    else
                    {
                        $null = $fileContent.AppendLine( ($templateColumnItem -f $p.PropertyName) )
                    }
                }
            }
            $null = $fileContent.AppendLine( $viewFooter )
            $null = $fileContent.AppendLine( $fileFooter )
    
            Write-Output $fileContent.ToString()
        }
    }
    
    
    function ConvertTo-CTypeSqlWrapper
    {
    <#
    .SYNOPSIS
    Wraps a SQL row in a wrapper object.
    .DESCRIPTION
    Wraps a SQL row in a wrapper object. The wrapper class must first be defined by
    Add-CType -SqlWrapper. The wrapped object has several advantages over the
    raw System.Data.DataRow object:
    (1) Property value System.DBNull is automatically converted to $null so that it is boolean-false in scripting
    (2) Type can be use in [OutputType([typename])] attributes
    (3) Type can be assigned formatting directives and other PowerShell type decorations
    (4) All properties are read-only
    (5) Hides unneeded properties of base SQL object
    
    .PARAMETER InputObject
    System.Data.DataRow object to be wrapped
    
    .PARAMETER TypeName
    Name of wrapper class, should be the same as for Add-CType
    
    .PARAMETER AddCType
    If specified, the type will be created automatically
    the first time an input object of this type is received,
    where the first object is a template.
    
    .PARAMETER AddCTypeScriptBlock
    If specified, the type will be created automatically
    the first time an input object of this type is received,
    where the first object is a template and this script block
    defines additional properties of the type. This implies -AddCType.
    Note the limitations in Notes below.
    
    .EXAMPLE
    $connection = New-Object System.Data.SqlClient.SqlConnection $connectionString
    $command = New-Object System.Data.SqlClient.SqlCommand $commandString,$connection
    $adapter = New-Object System.Data.SqlClient.SqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $null = $adapter.Fill($dataSet)
    $result = $tables[0].Rows
    $wrappedResult = $result | ConvertTo-CTypeSqlWrapper -TypeName MyCompany.MyNamespace.MyWrapperClass
    
    .NOTES
    Note that the type will be defined based on the first InputObject encountered.
    Even if subsequent objects have a different property list, the type cannot be changed.
    
    Note that you can define a type using AddCTypeScriptBlock, but because that type
    cannot be defined until the first template object is created, you may have difficulty
    using the type in an OutputType([typename]) block or a parameter definition.
    Consider generating the type definition with ConvertTo-CTypeDefinition
    and pasting the CType definition directly into your code.
    
    .LINK
    Add-CType
    CType
    ConvertTo-CTypeSqlDefinition
    #>
        [CmdletBinding()]
        param(
            [parameter(ValueFromPipeline=$true)][System.Data.DataRow]$InputObject,
            [parameter(Mandatory=$true,Position=0)][string]$TypeName,
            [switch]$AddCType,
            [ScriptBlock[]][parameter(Position=1)]$AddCTypeScriptBlock
        )
        process
        {
            if ($AddCType -or $AddCTypeScriptBlock)
            {
                if (-not $CType_AddedTypes[$TypeName])
                {
                    CType -TypeName $TypeName -TypeElement $AddCTypeScriptBlock,(SqlTemplateObject $InputObject)
                }
            }
            New-Object -TypeName $TypeName -ArgumentList $InputObject
        }
    }
    
    function CType
    {
    <#
    .SYNOPSIS
    Create a new type
    .PARAMETER TypeName
    Name of the new type. Include namespace e.g. "MyCompany.MyNamespace.MyClassName"
    .PARAMETER TypeElement
    One or more script blocks or type elements which define class properties and other elements of the class.
    The type elements may only contain objects on the list
    property, sqlproperty, parent, use, ref,SqlWrapper, SqlTemplateObject, and NoFormatData,
    and the script blocks must evaluate to objects of those types.
    The script block definition must begin on the same line as the CType invocation,
    or must be linked with backtick.
    .EXAMPLE
    # Creates a type with 4 properties, three of which are displayed in the default formatter.
    CType MyCompany.MyNamespace.MyClassName {
      parent MyCompany.MyNamespace.MyParentClass
      property string PropertyName1 -PropertyTableWidth 20 -PropertyKeywords trim
      if ($true)
      {
        property int PropertyName2  -PropertyTableWidth 15
      }
      property string PropertyName3 -PropertyTableWidth *
      property bool PropertyName4
    }
    .EXAMPLE
    # Creates a type with 4 properties, three SQL wrappers and one non-wrapped property.
    # The non-wrapped property can be set like any other read/write property, the others
    # always read from the equivalent property of the wrapped DataRow object.
    CType MyCompany.MyNamespace.MyClassName {
      parent MyCompany.MyNamespace.MyParentClass
      sqlproperty string PropertyName1 -PropertyTableWidth 20 -PropertyKeywords trim
      sqlproperty int PropertyName2  -PropertyTableWidth 15
      property string PropertyName3 -PropertyTableWidth *
      sqlproperty bool PropertyName4
    }
    .NOTES
    A type with a given name can only be defined once per PowerShell runspace.
    If you need to change it you will need to exit the runspace where it is defined.
    .LINK
    Add-CType
    #>
        [CmdletBinding()]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName,
            [parameter(Position=1)]$TypeElement
            )
        $typeElements = foreach ($element in $TypeElement)
        {
            if ($element)
            {
                if ($element -is [ScriptBlock])
                {
                    Invoke-Command -ScriptBlock $element
                }
                elseif ($element -is [ScriptBlock[]])
                {
                    $element | foreach {Invoke-Command -ScriptBlock $_}
                }
                else
                {
                    $element
                }
            }
        }
        foreach ($element in $typeElements)
        {
            if (-not ($element -is [CType.TypeElement]))
            {
                throw "$($MyInvocation.InvocationName): Invalid TypeElement $($element.GetType().FullName): TypeElement may only contain property, parent, use, ref,SqlWrapper, SqlTemplateObject, and NoFormatData, or script blocks generate them"
            }
        }
        [CType.Property[]]$properties = $typeElements | Where-Object {$_ -is [CType.Property]}
        [string[]]$parentTypes = $typeElements | Where-Object {$_ -is [CType.Parent]} | Select-Object -ExpandProperty ParentTypeName
        [string[]]$using = $typeElements | Where-Object {$_ -is [CType.Using]} | Select-Object -ExpandProperty Namespace
        [string[]]$referencedAssemblies = $typeElements | Where-Object {$_ -is [CType.ReferencedAssembly]} | Select-Object -ExpandProperty AssemblyName
        [System.Data.DataRow]$sqlTemplateObject = $null
        [System.Data.DataRow[]]$sqlTemplateObjects = @($typeElements | Where-Object {$_ -is [CType.SqlTemplateObject]} | Select-Object -ExpandProperty DataRow)
        if ($parentTypes)
        {
            if ($parentTypes.Count -gt 1)
            {
                throw 'You may only specify one parent type'
            }
            $parentType = $parentTypes[0]
        }
        else
        {
            $parentType = $null
        }
        if ($sqlTemplateObjects)
        {
            if ($sqlTemplateObjects.Count -gt 1)
            {
                throw 'You may only specify one SqlTemplateObject'
            }
            $sqlTemplateObject = $sqlTemplateObjects[0]
        }
        else
        {
            $sqlTemplateObject = $null
        }
        [bool]$noFormatData = [bool]($typeElements | Where-Object {$_ -is [CType.NoFormatData]} )
        [bool]$sqlWrapper = [bool]($typeElements | Where-Object {$_ -is [CType.SqlWrapper]} )
        $split = $TypeName.Split('.')
        if ($split.Count -lt 2)
        {
            throw 'You must specify full classname including namespace'
        }
        $classname = $split[-1]
        $namespace = $split[0..($split.Count-2)] -join '.'
    
        $properties | Add-CType -TypeName $TypeName `
                                -ParentTypeName $parentType `
                                -Using $using `
                                -ReferencedAssemblies $referencedAssemblies `
                                -SqlWrapper:$sqlWrapper `
                                -SqlTemplateObject $SqlTemplateObject `
                                -NoFormatData:$NoFormatData
    }
    
    function property
    {
    <#
    .SYNOPSIS
    Define a property for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.Property])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$PropertyType,
            [string][parameter(Mandatory=$true,Position=1)]$PropertyName,
            [string]$width,
            [switch]$trim
            )
        $propertyHash = @{
            PropertyType=$PropertyType
            PropertyName=$PropertyName
            }
        if ($width)
        {
            $propertyHash['PropertyTableWidth'] = $width
        }
        if ($trim)
        {
            $propertyHash['PropertyKeywords'] = "Trim"
        }
        New-Object -TypeName CType.Property -Property $propertyHash
    }
    
    function sqlproperty
    {
    <#
    .SYNOPSIS
    Define a SQL wrapper property for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.Property])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$PropertyType,
            [string][parameter(Mandatory=$true,Position=1)]$PropertyName,
            [string]$width,
            [switch]$trim
            )
        $propertyHash = @{
            PropertyType=$PropertyType
            PropertyName=$PropertyName
            }
        if ($width)
        {
            $propertyHash['PropertyTableWidth'] = $width
        }
        if ($trim)
        {
            $propertyHash['PropertyKeywords'] = ('SQLWrapper','Trim')
        }
        else
        {
            $propertyHash['PropertyKeywords'] = 'SQLWrapper'
        }
        New-Object -TypeName CType.Property -Property $propertyHash
    }
    
    function parent
    {
    <#
    .SYNOPSIS
    Specify a parent class for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.Parent])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$ParentTypeName
            )
        New-Object -TypeName CType.ParentType -Property @{
            ParentTypeName=$ParentTypeName
            }
    }
    
    function use
    {
    <#
    .SYNOPSIS
    Specify a Using reference for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.Using])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$Namespace
            )
        New-Object -TypeName CType.Using -Property @{
            Namespace=$Namespace
            }
    }
    
    function ref
    {
    <#
    .SYNOPSIS
    Specify a Referenced Assembly for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.ReferencedAssembly])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$AssemblyName
            )
        New-Object -TypeName CType.ReferencedAssembly -Property @{
            AssemblyName=$AssemblyName
            }
    }
    
    function SqlWrapper
    {
    <#
    .SYNOPSIS
    Specify that a CType should be a SQL Wrapper
    .LINK
    ConvertTo-CTypeSqlWrapper
    #>
        [CmdletBinding()]
        [OutputType([CType.SqlWrapper])]
        param(
            )
        New-Object -TypeName CType.SqlWrapper
    }
    
    function SqlTemplateObject
    {
    <#
    .SYNOPSIS
    Specify a SQL template object for use in CType
    #>
        [CmdletBinding()]
        [OutputType([CType.ReferencedAssembly])]
        param(
            [System.Data.DataRow][parameter(Mandatory=$true,Position=0)]$SqlTemplateObject
            )
        New-Object -TypeName CType.SqlTemplateObject -Property @{
            DataRow=$SqlTemplateObject
            }
    }
    
    function NoFormatData
    {
    <#
    .SYNOPSIS
    Specify that a CType should not generate formatting data
    .DESCRIPTION
    Specify that a CType should not generate formatting data.
    For example, you might perfer to generate the formatting data using
    Get-CTypeFormatPS1XML and enter this into the PS1XML for your module.
    #>
        [CmdletBinding()]
        [OutputType([CType.NoFormatData])]
        param(
            )
        New-Object -TypeName CType.NoFormatData
    }
    
    function ConvertTo-CTypeDefinition
    {
    <#
    .SYNOPSIS
    Generate a string representing a CType definition for the specified SQL object
    .DESCRIPTION
    Generate a string representing a CType definition for the specified SQL object.
    You can paste this string into your module code to generate a CType SQL wrapper
    for objects of the specified class, reordering the properties and adding
    width and keywords to specify the formatting for the type.
    .LINK
    CType
    Add-CType
    ConvertTo-CTypeSqlWrapper
    #>
        [CmdletBinding()]
        [OutputType([string])]
        param(
            [System.Data.DataRow][parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]$SqlTemplateObject
            )
        process
        {
    [System.Text.StringBuilder]$typeDefinition = New-Object -TypeName System.Text.StringBuilder -ArgumentList @"
    CType YourClassNameHere {
        SqlWrapper
        parent YourParentClassHere
    
    "@
            foreach ($column in $SqlTemplateObject.Table.Columns)
            {
                $name = $column.ColumnName
                $type = $column.DataType
                $null = $typeDefinition.AppendLine("    sqlproperty $type $name")
            }
            $null = $typeDefinition.AppendLine('}')
            $typeDefinition.ToString()
        }
    }
    
    function Test-CTypeIsDefined
    {
    <#
    .SYNOPSIS
    Test whether a CType type is already defined.
    .DESCRIPTION
    Test whether a CType type is already defined.
    Note that types may not be removed from a PowerShell session once defined.
    .PARAMETER TypeName
    Name for the type.
    .EXAMPLE
    if (-not (Test-CTypeIsDefined MyCompany.MyNamespace.ClassName))
    {
        CType MyCompany.MyNamespace.ClassName2 {
            CTypeProperty int Property1
            CTypeProperty string Property2
            CTypeProperty boolean Property3
        }
    }
    .NOTES
    This method is fast, but it only detects CType types, not .NET types generally.
    .LINK
    CType
    Add-CType
    #>
        [CmdletBinding()]
        [OutputType([bool])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName
            )
        return [bool]($CType_AddedTypes[$TypeName])
    }
    
    function Test-CTypeDotNetTypeIsDefined
    {
    <#
    .SYNOPSIS
    Test whether a type is already defined.
    .DESCRIPTION
    Test whether a type is already defined.
    Note that types may not be removed from a PowerShell session once defined.
    .PARAMETER TypeName
    Name for the type.
    .EXAMPLE
    if (-not (Test-CTypeDotNetTypeIsDefined MyCompany.MyNamespace.ClassName))
    {
        CType MyCompany.MyNamespace.ClassName2 {
            CTypeProperty int Property1
            CTypeProperty string Property2
            CTypeProperty boolean Property3
        }
    }
    .NOTES
    This method uses .NET reflection to search for the type, so it can take 100-200ms to run.
    Use it sparingly. Consider using Test-CTypeIsDefined instead.
    .LINK
    CType
    Add-CType
    #>
        [CmdletBinding()]
        [OutputType([bool])]
        param(
            [string][parameter(Mandatory=$true,Position=0)]$TypeName
            )
        $time = Measure-Command {
            $val = [bool]([appdomain]::CurrentDomain.GetAssemblies() | Where-Object DefinedTypes | Where-Object {$_.DefinedTypes.FullName -eq $TypeName})
        }
        Write-Verbose "$($MyInvocation.InvocationName): Searching for type $TypeName took $($time.TotalMilliseconds) milliseconds"
        $val
    }
    
  • content\CType\CType.psd1
  • content\CType\CType.psm1 Show
    # vstfpg06\Consol_06_TPC5 $/Nebula/Source/Ops Tools/current/Scripts/CType/CType.psm1
    
    # Remember the current directory
    $Script:ScriptDir = Split-Path $MyInvocation.MyCommand.Path
    
    . $Script:ScriptDir\CType.ps1
    
    Export-ModuleMember -Function '*-CType*',CType,property,sqlproperty,parent,use,ref,SqlWrapper,SqlTemplateObject,NoFormatData
    
  • content\CType\en-US\about_CType.help.txt Show
    TOPIC
        about_CType
    
    SHORT DESCRIPTION
        Create real .NET types without having to write .NET code, plus default table formatting!
    
    LONG DESCRIPTION
        CType enables module and script authors to easily create their own .NET types.
        Real .NET types created by CType have several advantages over raw PowerShell mechanisms
        such as hashtables and PSObjects:
        (1) CTypes can be used to create type-safe parameter declarations. If one function
            in your module returns objects of a CType, another function can declare a parameter
            which will only accept instances of the CType.
        (2) CTypes can be used in [OutputType([typename])] declarations for your functions
            which return them. This enables PowerShell (especially PowerShell ISE) to provide
            enhanced IntelliSense to help your user-scripters anticipate the available properties.
        (3) If you specify the -width parameter for any of your properties, CType will
            automatically configure table formatting for your CType.
    
        CType can also be used to create wrapper classes for SQL rows (System.Data.DataRow).
        These wrapper classes have all the above advantages plus the following:
        (4) Property value System.DBNull is automatically converted to $null so that it is
            boolean-false in scripting. This will help your users who may not be expecting that
            "if ($mydata.ThisPropertyIsDBNull)" will evaluate to $true and execute the if-block.
        (5) All properties are read-only for SQL wrapper classes.
        (6) CType wrapper classes hide unneeded members of the SQL base object, such as
            property Item[index] and methods AcceptChanges(), EndEdit() etc.
    
        CTypes only exist inside PowerShell runspaces where they are created,
        and disappear when the runspace exits. They do not in any way modify
        your Windows, .NET, or application binaries.
    
        CTypes can even be dynamic, meaning that the definition is created on-the-fly
        as your module loads or your script executes. The definition can contain
        PowerShell structures such as if, foreach etc, like any ScriptBlock. See the example below.
    
        You should call CType exactly once for each type, generally when your module is loaded.
        Only one .NET type (including CType) can exist with any given name.
        Once a CType has been defined with a particular name, you cannot change its definition
        other than by exiting the runspace and creating a new runspace.
    
        When choosing the name for your CType, you must specify a namespace which assures that
        your CType's full name (which includes the namespace) will not conflict with the full name
        of any .NET type defined by anyone else.
        Honor the guidelines specified in MSDN under "Names of Namespaces"!
        If you get this wrong:
        -- your CType may not load if conflicting .NET assemblies are already loaded; and/or
        -- your CType may block conflicting .NET assemblies from loading subsequently.
    
        The CType module has several functions besides "function CType":
        -- ConvertTo-CTypeSqlWrapper wraps a SQL DataRow instance into a CType you created
           using the SqlWrapper option.
        -- Add-CType offers an alternate syntax to create types. It does the exact same thing
           as "function CType", you can choose which syntax you prefer.
        -- ConvertTo-CTypeDefinition helps you create CType definitions which wrap
           a particular SQL object. You first generate an example SQL object, then run
           ConvertTo-CTypeDefinition, then paste the CType block it emits into your module
           and modify as needed (for example with formatting).
           In general you will use this function to help you write your module.
        -- Get-CTypeFormatPS1XML generates the formatting definition which CType uses to specify
           table formatting. You can use this if you prefer to put the formatting into a
           Format.ps1xml file in your module, rather than have CType add it automatically.
           In general you will use this function to help you write your module.
        -- Update-CTypeFormatData adds a formatting definition to the current PowerShell runspace.
           The definition could come from Get-CTypeFormatPS1XML or from elsewhere.
        -- Test-CTypeIsDefined tests whether you have already defined a particular CType.
        -- Test-CTypeDotNetTypeIsDefined tests whether a particular CType has already been defined,
           whether it is a CType or any other type.
        -- Functions property, sqlproperty, parent, use, ref, SqlWrapper,
           SqlTemplateObject and NoFormatData, are all helpers used in CType definitions.
    
        The CType module doesn't do anything you couldn't do yourself with Add-Type and
        Update-FormatData -PrependPath. CType saves you the trouble of learning C#
        to write the type definition and Format.ps1xml to write the table formatting.
        If you have more complex needs you may wind up needing to fall back to C#,
        but don't forget that PowerShell can add custom properties and methods to any type
        including CTypes with Add-Member and/or Types.ps1xml (see "Get-Help about_Types.ps1xml").
    
    EXAMPLES
        (1) Here is an example of how to use CType to create a type and use it in your functions:
    
            CType MyCompany.MyNamespace.MyClassName {
              property string PropertyName1 -width 20 -trim
              if ($true)
              {
                property int PropertyName2  -width 15
              }
              property string PropertyName3 -width *
              property bool PropertyName4
            }
    
            function New-MyThing
            {
                [CmdletBinding()]
                [OutputType([MyCompany.MyNamespace.MyClassName])]
                param(
                    [string]$Value
                    )
                return New-Object -TypeName MyCompany.MyNamespace.MyClassName `
                        -Property @{PropertyName3 = $value}
            }
    
            function Get-MyThing
            {
                [CmdletBinding()]
                param(
                    [MyCompany.MyNamespace.MyClassName]$Thing
                    )
                $thing.PropertyName3
            }
    
            $o = New-MyThing -Value 'Value'
            'object default formatting is'
            $o
            'Get-MyThing returns'
            Get-MyThing -Thing $o
    
        which returns
    
            object default formatting is
    
            PropertyName1        PropertyName2   PropertyName3                                                                                                                                                                                                               
            -------------        -------------   -------------                                                                                                                                                                                                               
                                 0               Value                                                                                                                                                                                                                       
            Get-MyThing returns
            Value
    
        Note the following:
        -- You can use the full PowerShell language inside the type definition.
        -- The first '{' in the CType definition must be on the same line,
           unless you use backtick '`'.
        -- Get-MyThing will refuse any parameter not of the type you defined.
    
        (2) Here is an example of creating and using a SQLWrapper class:
    
            CType MyCompany.MyNamespace.MyClassName {
              sqlproperty string PropertyName1 -width 20 -trim
              sqlproperty int PropertyName2  -width 15
              property string PropertyName3 -width *
              sqlproperty bool PropertyName4
            }
            $obj = New-Object -TypeName MyCompany.MyNamespace.MyClassName `
                              -ArgumentList $myDataRowObject
            $obj.PropertyName3 = 'SomeString'
    
            Note that properties 1, 2 and 4 get their values from $myDataRowObject,
            but the value of property 3 is independent and can be set explicitly.
    
    
    KEYWORDS
        Type, Types, Format, FormatData
    
    SEE ALSO
        Get-Help about_Format.ps1xml
        Get-Help about_Types.ps1xml
        Add-Type
        Update-FormatData
        In MSDN search for "Names of Namespaces"
    
  • tools\CType.msi

Virus Scan Results

In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).

Chocolatey Pro provides runtime protection from possible malware.

Dependencies

This package has no dependencies.

Package Maintainer(s)

Software Author(s)

  • Jon Newman

Tags

Version History

Version Downloads Last updated Status
CType 1.00.0003 256 Wednesday, March 25, 2015 approved

Discussion for the CType Package

Ground rules:

  • This discussion is only about CType and the CType package. If you have feedback for Chocolatey, please contact the google group.
  • This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
  • The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
  • Tell us what you love about the package or CType, or tell us what needs improvement.
  • Share your experiences with the package, or extra configuration or gotchas that you've found.
  • If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.

comments powered by Disqus
Chocolatey.org uses cookies to enhance the user experience of the site.
Ok