C#: I'm looking for a way to create new "primitive" types with additional constraints which are visible at coding time to users of the type : Suppose I have an entity in my universe of discourse called a `Widget`. Widgets are passed around between multiple distributed applications. All systems communicate through a messaging system. The messaging system passes a "common data model" (CDM) instance of the `Widget` around, where all applications translate to and from the CDM, and the communication follows the event-carried-state-transfer pattern.<sup>[1]</sup>

Suppose the `Widget` has an attribute called a `WidgetCode`. This attribute is defined (by the system of record) to be an alphanumeric value of length exactly 8, and is exposed in the Common data model. 

I might implement that in the CDM as follows:
``` lang-cs
class Widget 
{ 
    private string _WidgetCode;
    public string WidgetCode 
    { 
        get => _WidgetCode;
        set 
        { 
            if (value.Length != 8) throw new InvalidCastException();
            _WidgetCode = value;
        }
    }
}
```   
This is OK, but not ideal. The constraint on length is not declarative, therefore it is not visible at design time to a consumer of this class. It will only be found if, at runtime, someone happens to try to write in a value which is not 8 characters long.

There may also be other entities which have a `WidgetCode` as an attribute. For example, a `Sale` may contain the `WidgetCode` of the `Widget` which was sold <sup>[2]</sup>.

So the data element `WidgetCode` appears in multiple places. So it would make sense to say "You know what, this `WidgetCode` thing is actually a type in its own right. In the context of the CDM it's a primitive<sup>[3]</sup>:

``` lang-cs
struct WidgetCode { ... }

class Widget
{
    public WidgetCode widgetCode { get; set; }
    // ...
}

class Sale
{
    // ...
    public WidgetCode widgetCode { get; set; }
}    
```

Now the length constraint on the WidgetCode type can be implemented by the type itself, but it's still going to be a runtime constraint, not a declarative constraint which is visible to the developer at coding-time.

Is there any elegant way in C# to create a new "primitive", with constraints which are "declarative" and go beyond those inherent constraints provided by language primitives?

---
[1] https://martinfowler.com/articles/201701-event-driven.html

[2] I recognize that this is more like a DTO that exposes the structure of, for example, a table in a SQL database. I am not describing a `Sale` class which contains an instance of a `Widget` class like you might expect in, say, an ORM. But remember, what I'm describing is the *content of a message* representing a new sale. In other words, someone created a Sale in some system, and we want to send that data to another system in order to say "Hello other system, here is a Sale which was just created". When we do that, we're clearly cannot pass the lazily-loaded object graph as the message body.

[3] Obviously there would be a naming problem here given conventional capitalization guidelines, so you'll have to excuse the camelCase name.