Shapely 0.0.3

dotnet add package Shapely --version 0.0.3
                    
NuGet\Install-Package Shapely -Version 0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shapely" Version="0.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shapely" Version="0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Shapely" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shapely --version 0.0.3
                    
#r "nuget: Shapely, 0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shapely@0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shapely&version=0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Shapely&version=0.0.3
                    
Install as a Cake Tool

Shapely

A C# source generator inspired by TypeScript's utility types (Pick, Omit) that simplifies creating DTOs and other derived types. Instead of hand-writing classes that are mostly copies of your domain models, you describe the shape you want and Shapely generates it.

Why Shapely?

When building APIs you often need types that are slight variations of your domain models — a response DTO that omits an internal field, a command object that picks only a few properties, or a composed type that pulls properties from two different services. In TypeScript you'd reach for Pick<T, K> or Omit<T, K>. Shapely brings that pattern to C#, with additional ideas suited to the language.

A common scenario: one service returns a type where a property contains just IDs. You need to enrich it with full objects from a second service. With Shapely you can model that as a shaped class that picks the bulk of its properties from the first type and replaces the ID property's type with the full type from the second service — all without manually writing out every property.

Installation

dotnet add package Shapely

Getting Started

Decorate a partial class with one or more shaping attributes:

using Shapely.Abstractions;

[All(typeof(Product))]
public partial class ProductDto { }

Shapely generates all public properties from Product into ProductDto at compile time. No mapping code, no property duplication.

Shaping Attributes

All — copy every property

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string InternalCode { get; set; }
}

[All(typeof(Product))]
public partial class ProductDto { }

// Generated:
// public partial class ProductDto
// {
//     public int Id { get; set; }
//     public string Name { get; set; }
//     public decimal Price { get; set; }
//     public string InternalCode { get; set; }
// }

Pick — include only named properties

[Pick(typeof(Product), nameof(Product.Id), nameof(Product.Name))]
public partial class ProductSummaryDto { }

// Generated: Id and Name only

Omit — exclude named properties

[Omit(typeof(Product), nameof(Product.InternalCode))]
public partial class ProductPublicDto { }

// Generated: Id, Name, Price — InternalCode dropped

Composing from Multiple Sources

Stack multiple attributes to pull properties from more than one type. This is especially useful when you're composing a response from multiple services:

// Service A returns orders with a list of product IDs
public class Order
{
    public int OrderId { get; set; }
    public DateTime PlacedAt { get; set; }
    public IEnumerable<int> ProductIds { get; set; }
}

// Service B returns full product data
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// Composed response: everything from Order except the IDs,
// plus the resolved products from Service B
[Omit(typeof(Order), nameof(Order.ProductIds))]
[Pick(typeof(Product), nameof(Product.Name))]
public partial class OrderWithProductsDto { }

Shapely raises a compile-time error (SHAPELY002) if two sources contribute a property with the same name.

Type Transformations

After shaping, you can transform property types without changing the property selection.

TransformAllTypes — replace a type everywhere

[All(typeof(Product))]
[TransformAllTypes(typeof(decimal), typeof(double))]
public partial class ProductApiDto { }

// Price becomes double instead of decimal

TransformType — replace a type on specific properties

[All(typeof(Order))]
[TransformType(typeof(IEnumerable<int>), typeof(IEnumerable<Product>), nameof(Order.ProductIds))]
public partial class EnrichedOrderDto { }

// ProductIds becomes IEnumerable<Product>

Accessor Transformations

Control whether generated properties use set or init accessors.

TransformAllSetAccessors — change all setters

[All(typeof(Product))]
[TransformAllSetAccessors(SetAccessor.Init)]
public partial class ImmutableProductDto { }

// All properties become init-only

TransformSetAccessor — change specific setters

[All(typeof(Product))]
[TransformSetAccessor(SetAccessor.Init, nameof(Product.Id))]
public partial class ProductDto { }

// Only Id becomes init-only; others stay as set

Analyzer Diagnostics

Shapely ships Roslyn analyzers that give you compile-time feedback:

ID Description
SHAPELY001 Class with Shapely attributes must be partial
SHAPELY002 Two sources produce a property with the same name
SHAPELY003 Property named in a type transformation does not exist on the class
SHAPELY004 A property appears in duplicate type transformation rules
SHAPELY005 Property named in Pick/Omit does not exist on the source type
SHAPELY006 A property appears in duplicate accessor transformation rules
SHAPELY007 Property named in an accessor transformation does not exist on the generated class

Working with Mapperly

Shapely works well alongside Mapperly for object mapping, but there is an ordering constraint: Roslyn source generators run in parallel, so Shapely-generated types are not visible to the Mapperly generator in the same project. The workaround is to keep your Shapely-shaped types in a separate project from your Mapperly mappers. That way the shaped types are compiled before Mapperly's generator runs, and Mapperly can see them normally.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.3 32 5/6/2026
0.0.2 35 5/5/2026