Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Benchmarks/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ dotnet_diagnostic.IDE0005.severity = none

# CA1515: Consider making public types internal
# Justification: Won't be exposed in the NuGet packages
dotnet_diagnostic.CA1515.severity = none
dotnet_diagnostic.CA1515.severity = none

# CA1822: Mark members as static
# Justification: Benchmark methods shouldn't be static
dotnet_diagnostic.CA1822.severity = none
dotnet_diagnostic.CA1707.severity = none
99 changes: 49 additions & 50 deletions Benchmarks/Schema.NET.Benchmarks/Core/BookBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace Schema.NET.Benchmarks.Core;

using System;
using System.Collections.Generic;

public class BookBenchmark : SchemaBenchmarkBase
{
Expand All @@ -15,66 +14,66 @@ public override Thing InitialiseThing() =>
Name = "J.D. Salinger",
},
Url = new Uri("https://www.barnesandnoble.com/store/info/offer/JDSalinger"),
WorkExample = new List<ICreativeWork?>
{
new Book
WorkExample =
[
new Book
{
Isbn = "031676948",
BookEdition = "2nd Edition",
BookFormat = BookFormatType.Hardcover,
PotentialAction = new ReadAction
{
Isbn = "031676948",
BookEdition = "2nd Edition",
BookFormat = BookFormatType.Hardcover,
PotentialAction = new ReadAction
Target = new EntryPoint
{
Target = new EntryPoint
{
UrlTemplate = "https://www.barnesandnoble.com/store/info/offer/0316769487?purchase=true",
ActionPlatform = new List<Uri?>
{
new Uri("https://schema.org/DesktopWebPlatform"),
new Uri("https://schema.org/IOSPlatform"),
new Uri("https://schema.org/AndroidPlatform"),
},
},
ExpectsAcceptanceOf = new Offer
UrlTemplate = "https://www.barnesandnoble.com/store/info/offer/0316769487?purchase=true",
ActionPlatform =
[
new Uri("https://schema.org/DesktopWebPlatform"),
new Uri("https://schema.org/IOSPlatform"),
new Uri("https://schema.org/AndroidPlatform"),
],
},
ExpectsAcceptanceOf = new Offer
{
Price = 6.99M,
PriceCurrency = "USD",
EligibleRegion = new Country
{
Price = 6.99M,
PriceCurrency = "USD",
EligibleRegion = new Country
{
Name = "US",
},
Availability = ItemAvailability.InStock,
Name = "US",
},
Availability = ItemAvailability.InStock,
},
},
new Book
},
new Book
{
Isbn = "031676947",
BookEdition = "1st Edition",
BookFormat = BookFormatType.EBook,
PotentialAction = new ReadAction
{
Isbn = "031676947",
BookEdition = "1st Edition",
BookFormat = BookFormatType.EBook,
PotentialAction = new ReadAction
Target = new EntryPoint
{
Target = new EntryPoint
{
UrlTemplate = "https://www.barnesandnoble.com/store/info/offer/031676947?purchase=true",
ActionPlatform = new List<Uri?>
{
new Uri("https://schema.org/DesktopWebPlatform"),
new Uri("https://schema.org/IOSPlatform"),
new Uri("https://schema.org/AndroidPlatform"),
},
},
ExpectsAcceptanceOf = new Offer
UrlTemplate = "https://www.barnesandnoble.com/store/info/offer/031676947?purchase=true",
ActionPlatform =
[
new Uri("https://schema.org/DesktopWebPlatform"),
new Uri("https://schema.org/IOSPlatform"),
new Uri("https://schema.org/AndroidPlatform"),
],
},
ExpectsAcceptanceOf = new Offer
{
Price = 1.99M,
PriceCurrency = "USD",
EligibleRegion = new Country
{
Price = 1.99M,
PriceCurrency = "USD",
EligibleRegion = new Country
{
Name = "UK",
},
Availability = ItemAvailability.InStock,
Name = "UK",
},
Availability = ItemAvailability.InStock,
},
},
},
},
],
};
}
55 changes: 29 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
[![Schema.NET NuGet Package](https://img.shields.io/nuget/v/SchemaDotNet.svg)](https://www.nuget.org/packages/SchemaDotNet)
# (Temporary?) Fork of [Schema.NET](https://github.com/RehanSaeed/Schema.NET)
### Changes:
- Add targets for .NET 8 - 10
- Add support for [collection expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/collection-expressions)
- Performance improvements
### Why the fork?
> I created this fork for to use in a large webshop, I initially wanted the package to target .net 8.<br/>
> But once begun, I added support for collection expressions, and other small tweaks.

<hr/>

[![SchemaDotNet NuGet Package](https://img.shields.io/nuget/v/SchemaDotNet.svg)](https://www.nuget.org/packages/SchemaDotNet)
[![build](https://github.com/TimmyMC/Schema.NET/actions/workflows/build.yml/badge.svg)](https://github.com/TimmyMC/Schema.NET/actions/workflows/build.yml)

[//]: # ([![Schema.NET NuGet Package Downloads]&#40;https://img.shields.io/nuget/dt/SchemaDotNet&#41;]&#40;https://www.nuget.org/packages/SchemaDotNet&#41;)
[![SchemaDotNet NuGet Package Downloads](https://img.shields.io/nuget/dt/SchemaDotNet)](https://www.nuget.org/packages/SchemaDotNet)

Schema.org objects turned into strongly typed C# POCO classes for use in .NET. All classes can be serialized into JSON/JSON-LD and XML, typically used to represent structured data in the `head` section of `html` page.

Expand Down Expand Up @@ -33,7 +43,7 @@ If writing the result into a `<script>` element, be sure to use the `.ToHtmlEsca

## What is Schema.org?

[schema.org](https://schema.org) defines a set of standard classes and their properties for objects and services in the real world. This machine readable format is a common standard used across the web for describing things.
[schema.org](https://schema.org) defines a set of standard classes and their properties for objects and services in the real world. This machine-readable format is a common standard used across the web for describing things.

## Where is Schema.org Used?

Expand Down Expand Up @@ -77,7 +87,7 @@ Windows UWP apps let you share data using schema.org classes. [Here](https://doc

schema.org defines classes and properties, where each property can have a single value or an array of multiple values. Additionally, properties can have multiple types e.g. an `Address` property could have a type of `string` or a type of `PostalAddress` which has it's own properties such as `StreetAddress` or `PostalCode` which breaks up an address into it's constituent parts.

To facilitate this Schema.NET uses some clever C# generics and implicit type conversions so that setting a single or multiple values is possible and that setting a `string` or `PostalAddress` is also possible:
To facilitate this SchemaDotNet uses some clever C# generics and implicit type conversions so that setting a single or multiple values is possible and that setting a `string` or `PostalAddress` is also possible:

```C#
// Single string address
Expand All @@ -89,11 +99,11 @@ var organization = new Organization()
// Multiple string addresses
var organization = new Organization()
{
Address = new List<string>()
{
Address =
[
"123 Old Kent Road E10 6RL",
"456 Finsbury Park Road SW1 2JS"
}
]
};

// Single PostalAddress address
Expand All @@ -109,8 +119,8 @@ var organization = new Organization()
// Multiple PostalAddress addresses
var organization = new Organization()
{
Address = new List<PostalAddress>()
{
Address =
[
new PostalAddress()
{
StreetAddress = "123 Old Kent Road",
Expand All @@ -121,17 +131,17 @@ var organization = new Organization()
StreetAddress = "456 Finsbury Park Road",
PostalCode = "SW1 2JS"
}
}
]
};

// Mixed Author types
var book = new Book()
{
Author = new List<object>()
{
Author =
[
new Organization() { Name = "Penguin" },
new Person() { Name = "J.D. Salinger" }
}
]
};

// Deconstruct a property containing mixed types
Expand All @@ -145,18 +155,11 @@ This magic is all carried out using [implicit conversion operators](https://docs

## More Examples

For more examples and actual running code samples, take a look at the unit tests in the project source code.

## Schema.NET.Pending

There are many pending types on [schema.org](https://schema.org) which are not yet fully formed and ready for production. If you need to use these, you can install the [Schema.NET.Pending](https://www.nuget.org/packages/SchemaDotNet.Pending) NuGet package instead of [Schema.NET](https://www.nuget.org/packages/SchemaDotNet). This package contains all released schema types as well as all pending types.

[![Schema.NET.Pending NuGet Package](https://img.shields.io/nuget/v/Schema.NET.Pending.svg)](https://www.nuget.org/packages/SchemaDotNet.Pending)
For more examples and actual running code samples, take a look at the [unit tests](https://github.com/TimmyMC/Schema.NET/tree/main/Tests/Schema.NET.Test/Examples) in the project source code.

[//]: # ([![Schema.NET.Pending NuGet Package Downloads]&#40;https://img.shields.io/nuget/dt/Schema.NET.Pending&#41;]&#40;https://www.nuget.org/packages/SchemaDotNet.Pending&#41;)
## SchemaDotNet.Pending

## Continuous Integration
There are many pending types on [schema.org](https://schema.org) which are not yet fully formed and ready for production. If you need to use these, you can install the [SchemaDotNet.Pending](https://www.nuget.org/packages/SchemaDotNet.Pending) NuGet package instead of [SchemaDotNet](https://www.nuget.org/packages/SchemaDotNet). This package contains all released schema types as well as all pending types.

| Name | Operating System | Status | History |
| :--- | :--- | :--- |:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| GitHub Actions | Ubuntu, Mac & Windows | [![GitHub Actions Status](https://github.com/TimmyMC/Schema.NET/workflows/Build/badge.svg?branch=main)](https://github.com/TimmyMC/Schema.NET/actions) | [![GitHub Actions Build History](https://buildstats.info/github/chart/TimmyMC/Schema.NET?branch=main&includeBuildsFromPullRequest=false)](https://github.com/TimmyMC/Schema.NET/actions) |
[![SchemaDotNet.Pending NuGet Package](https://img.shields.io/nuget/v/SchemaDotNet.Pending.svg)](https://www.nuget.org/packages/SchemaDotNet.Pending)
[![SchemaDotNet.Pending NuGet Package Downloads](https://img.shields.io/nuget/dt/SchemaDotNet.Pending)](https://www.nuget.org/packages/SchemaDotNet.Pending)
3 changes: 3 additions & 0 deletions Source/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
# CA1716: Identifiers should not match keywords
# Justification: Ignore Parameters to avoid breaking changes
dotnet_code_quality.CA1716.analyzed_symbol_kinds = Namespace, NamedType, Method, Property, Event

# CA1710: Identifiers should have correct suffix
dotnet_code_quality.CA1710.additional_required_suffixes = IEnumerable->{}|IReadOnlyCollection->{}|IValues->Values
2 changes: 0 additions & 2 deletions Source/Common/IValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
/// <summary>
/// An <see cref="IEnumerable"/> with a count.
/// </summary>
#pragma warning disable CA1710 // Identifiers should have correct suffix
#pragma warning disable CA1010 // Collections should implement generic interface
public interface IValues : IEnumerable
#pragma warning restore CA1010 // Collections should implement generic interface
#pragma warning restore CA1710 // Identifiers should have correct suffix
{
/// <summary>
/// Gets the count.
Expand Down
37 changes: 21 additions & 16 deletions Source/Common/OneOrMany{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ namespace Schema.NET;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;

/// <summary>
/// A single or list of values.
/// </summary>
/// <typeparam name="T">The type of the values.</typeparam>
/// <seealso cref="ICollection{T}" />
/// <seealso cref="IReadOnlyCollection{T}" />
[CollectionBuilder(typeof(OneOrManyBuilder), nameof(OneOrManyBuilder.Create))]
#pragma warning disable CA1710 // Identifiers should have correct suffix.
public readonly struct OneOrMany<T>
public readonly struct OneOrMany<T> : IReadOnlyCollection<T>, IValues, IEquatable<OneOrMany<T>>
#pragma warning restore CA1710 // Identifiers should have correct suffix.
: IReadOnlyCollection<T>, IValues, IEquatable<OneOrMany<T>>
{
private readonly T[]? collection;

Expand All @@ -40,7 +41,7 @@ public OneOrMany(T? item)
/// Initializes a new instance of the <see cref="OneOrMany{T}"/> struct.
/// </summary>
/// <param name="span">The span of values.</param>
public OneOrMany(ReadOnlySpan<T?> span)
public OneOrMany(params ReadOnlySpan<T?> span)
{
if (!span.IsEmpty)
{
Expand All @@ -49,9 +50,8 @@ public OneOrMany(ReadOnlySpan<T?> span)

if (typeof(T) == typeof(string))
{
for (var i = 0; i < span.Length; i++)
foreach (var item in span)
{
var item = span[i];
if (!string.IsNullOrWhiteSpace(item as string))
{
items[index] = item;
Expand All @@ -61,9 +61,8 @@ public OneOrMany(ReadOnlySpan<T?> span)
}
else
{
for (var i = 0; i < span.Length; i++)
foreach (var item in span)
{
var item = span[i];
if (item is not null)
{
items[index] = item;
Expand Down Expand Up @@ -93,12 +92,6 @@ public OneOrMany(ReadOnlySpan<T?> span)
this.HasOne = false;
}

/// <summary>
/// Initializes a new instance of the <see cref="OneOrMany{T}"/> struct.
/// </summary>
/// <param name="array">The array of values.</param>
public OneOrMany(params T?[] array) : this(array.AsSpan()) { }

/// <summary>
/// Initializes a new instance of the <see cref="OneOrMany{T}"/> struct.
/// </summary>
Expand Down Expand Up @@ -210,9 +203,9 @@ public IEnumerator<T> GetEnumerator()
{
if (this.collection is not null)
{
for (var i = 0; i < this.collection.Length; i++)
foreach (var item in this.collection)
{
yield return this.collection[i];
yield return item;
}
}
}
Expand Down Expand Up @@ -294,3 +287,15 @@ public bool Equals(OneOrMany<T> other)
/// <returns>A <see cref="ReadOnlySpan{T}"/> wrapping the current items.</returns>
public ReadOnlySpan<T> AsSpan() => this.collection.AsSpan();
}

/// <summary>
/// Contains the generic static constructors needed to support collection expressions.
/// </summary>
public static class OneOrManyBuilder
{
/// <summary>
/// Initializes a new instance of the <see cref="OneOrMany{T}"/> struct.
/// </summary>
/// <param name="items">The span of values.</param>
public static OneOrMany<T> Create<T>(ReadOnlySpan<T> items) => new(items);
}
Loading
Loading