DuckType.Core 1.0.6

There is a newer version of this package available.
See the version list below for details.
dotnet add package DuckType.Core --version 1.0.6
                    
NuGet\Install-Package DuckType.Core -Version 1.0.6
                    
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="DuckType.Core" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DuckType.Core" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="DuckType.Core" />
                    
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 DuckType.Core --version 1.0.6
                    
#r "nuget: DuckType.Core, 1.0.6"
                    
#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 DuckType.Core@1.0.6
                    
#: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=DuckType.Core&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=DuckType.Core&version=1.0.6
                    
Install as a Cake Tool

DuckType Library

Overview

The DuckType Library is designed to enable "duck typing" in .NET, allowing objects to be dynamically cast to interfaces with compatible methods and properties. It also introduces a "smart" object mechanism, which enhances objects with additional behaviors, validation, and default implementations.

This library is primarily intended for scenarios where interfaces must be dynamically applied to objects that do not explicitly implement them, enabling more flexible coding practices without needing concrete implementations. It also supports validation and behavior customization through "smart" objects, making it suitable for more advanced scenarios requiring enhanced property management.


Key Features

  1. Duck Typing: Allows casting objects to interfaces based on compatible signatures, even if the objects do not explicitly implement the interface.
  2. Smart Objects: Enhances objects by adding validation, default behaviors, and dynamic behavior customization.
  3. Fluent Behavior Configuration: Provides a fluent API to configure and apply behaviors on properties or methods.
  4. Default Implementations: Enables interfaces with default implementations, which can be used when the object lacks specific method implementations.
  5. Behavioral Modifications: Allows adding custom behaviors such as email validation or conditional method execution based on external conditions (e.g., day or night).

Getting Started

Installation

Add the library to your project.

dotnet add package DuckType.Core

Basic Usage

  1. Duck Typing Objects

    The AsDuck<T>() method allows you to cast any object to a specified interface T if the object’s properties and methods match the interface’s requirements.

    var anonymous = new { MyProperty = "Hello" };
    var duck = anonymous.AsDuck<IFoo>();
    DoStuffWithAnIFoo(duck);  // Would not be possible with anonymouse
    
  2. Creating Smart Objects

    Smart objects are created using the MakeSmart() method, enabling additional behaviors and validation on properties.

         [SmartEmail] 
         public string EmailAddress { get; set; }
    
         var smart = original.MakeSmart();
    
         //Will throw a validation exception
         smart.EmailAddress = "not an email adress"
    

    Given the custom attribute:

         public class AllowOnlyEmailAddress : AllowOnlyRegexMatch
         {
             //Credits goes to bortzmeyer https://stackoverflow.com/a/201378/2968001
             const string ValidEmailRegex = @"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])";
    
             public AllowOnlyEmailAddress() : base(ValidEmailRegex)  { }
         }
    

Duck Typing Examples

The DuckTypeTests suite demonstrates how to apply duck typing to various objects.

  • DuckTypeAnAnonymousObject: Shows casting an anonymous object to an interface.
  • DuckTypeWriteProperty: Verifies property modification on a duck-typed object.
  • DuckTypeBazAsFoo: Demonstrates type mismatching that results in an exception.

Example: Cast and Modify Properties

var foo = new Foo { MyProperty = "Initial" };
var duck = foo.AsDuck<IFoo>();
duck.MyProperty = "Modified";
Console.WriteLine(duck.MyProperty);  // Outputs: Modified

Smart Object Examples

The SmartBasicTests and SmartPhase1Tests demonstrate using smart objects with validation and custom behaviors.

  • SmartObjectShouldEqualsTheOriginal: Ensures that smart objects retain original property values and structure.
  • TheSmartEmailPropertyCanBeSetWithAValidValue: Shows how to validate email addresses using custom behaviors.
  • VampireDoNothingDuringDayLight: Implements conditional method execution based on time of day, using VampireBehavior.

Example: Applying Custom Behaviors

var original = new MyClass();
var smart = original.MakeSmart();
smart.GetSmartController()
     .ForProperty(e => e.EmailAddress)
     .AddBehavior(new AllowOnlyEmailAddress());

smart.EmailAddress = "valid.email@example.com"; // Works fine
smart.EmailAddress = "invalid";                 // Throws SmartException

Additional Functionalities

Configuring Default Implementations

In cases where methods are not implemented on the object, the library can provide default implementations using the UseDefaultImplementations option.

var anonymous = new {};
var duck = anonymous.AsDuck<IQuux>(options => options.UseDefaultImplementations());
duck.DoStuff();  // Executes the default implementation

Using Behaviors with External Conditions

Behavior customization allows for complex interactions. For example, methods can be executed only under certain conditions, such as time-dependent behavior.

var dayNightProvider = Mock.Of<IDayNightProvider>();
Mock.Get(dayNightProvider).Setup(e => e.IsDayLight()).Returns(false);

var quux = new Quux();
var smartQuux = quux.MakeSmart();
smartQuux.GetSmartController()
         .ForAction(e => e.DoStuff())
         .AddBehavior(new VampireBehavior(dayNightProvider));

smartQuux.DoStuff();  // Executes normally if it’s nighttime

Acknowledgement

The heavy lifting was already been done by Castle.Core.

Contributing

We welcome contributions! Please refer to CONTRIBUTING.md for details on how to participate.


License

This library is released under the MIT License. See LICENSE for details.

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 netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen 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.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on DuckType.Core:

Package Downloads
DuckType.Adaptors.FluentValidation

Package Description

DuckType

Package Description

DuckType.Extensions

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.9 331 12/12/2024
1.0.8 265 12/12/2024
1.0.7 296 11/14/2024
1.0.6 187 11/7/2024