Giter Site home page Giter Site logo

siberaindustries / extensions.dictionary Goto Github PK

View Code? Open in Web Editor NEW
7.0 3.0 0.0 156 KB

A library to convert a dictionary out of a given object or an object out of a dictionary.

License: MIT License

C# 100.00%
netstandard dictionary csharp extensions converter

extensions.dictionary's Introduction

Extensions.Dictionary

NuGet .NET Core Quality Gate Status Coverage

Introduction

The easiest way to start using Extensions.Dictionary is to install it’s Nuget package. In Visual Studio open Package Manager console and type the following:

Install-Package Extensions.Dictionary

In the source file where you will be using Dictionary Extensions import the namespace:

using Extensions.Dictionary;

Sample class:

public class Person
{
    [DataMember(Name = "Name1")]
    public string Firstname { get; set; }

    [IgnoreDataMember]
    public string Lastname { get; set; }
}

Convert an instance to a dictionary:

var person = new Person { Firstname = "foo", Lastname = "bar" };

// Option 1: Convert all public properties and instance fields
var dictionary1 = person.ToDictionary(); 

// Option 2: Same as option 1 + respect DataContract attributes (DataMember / IgnoreDataMember)
var settings = new ConverterSettings { Resolver = new DataContractResolver() };
var dictionary2 = person.ToDictionary(settings);

// dictionary1: <Firstname = foo; Lastname = bar>
// dictionary2: <Name1 = foo>

Convert a dictionary back to it's typed instance:

// Option 1
var person1 = dictionary.ToInstance<Person>();

// Option 2
var settings = new ConverterSettings { Resolver = new DataContractResolver() };
var person2 = dictionary.ToInstance<Person>(settings);

Extensibility

Custom MemberConverter

This sample creates a custom converter from MemberConverter<T> that overrides conversion for the System.Numerics.Vector4 class.

public class Vector4Converter : MemberConverter<Vector4>
{
    public override IDictionary<string, object> ToDictionary(Vector4 value, ConverterSettings settings)
    {
        return new Dictionary<string, object>(4)
        {
            { nameof(Vector4.W), value.W },
            { nameof(Vector4.X), value.X },
            { nameof(Vector4.Y), value.Y },
            { nameof(Vector4.Z), value.Z },
        };
    }

    public override Vector4 ToInstance(IDictionary<string, object?> value, ConverterSettings settings)
    {
        return new Vector4
        {
            W = float.Parse(value[nameof(Vector4.W)]?.ToString(), settings.Culture),
            X = float.Parse(value[nameof(Vector4.X)]?.ToString(), settings.Culture),
            Y = float.Parse(value[nameof(Vector4.Y)]?.ToString(), settings.Culture),
            Z = float.Parse(value[nameof(Vector4.Z)]?.ToString(), settings.Culture),
        };
    }
}
// Usage
var plane = new Plane(1f, 1f, 1f, .1f);

var settings = new ConverterSettings();
settings.Converters.Add(new Vector4Converter());

var dict = plane.ToDictionary(settings);

Custom Resolver

It is possible to customize the member name / value extraction. Just implement the provided ISerializerResolver interface. The following code snipped shows an example of a Json.NET resolver:

public class JsonNetResolver : ISerializerResolver
{
    public string GetMemberName(MemberInfo memberInfo)
    {
        if (memberInfo == null)
        {
            throw new ArgumentNullException(nameof(memberInfo));
        }

        var attribute = memberInfo.GetCustomAttribute<JsonPropertyAttribute>();
        return attribute?.PropertyName ?? memberInfo.Name;
    }

    public object GetMemberValue(MemberInfo memberInfo, object instance)
    {
        switch (memberInfo?.MemberType)
        {
            case MemberTypes.Property:
                return ((PropertyInfo)memberInfo).GetValue(instance);
            case MemberTypes.Field:
                return ((FieldInfo)memberInfo).GetValue(instance);
            case null:
                throw new ArgumentNullException(nameof(memberInfo));
            default:
                throw new NotSupportedException(memberInfo.MemberType + " not supported.");
        }
    }

    public MemberInfo[] GetMemberInfos(Type type)
    {
        return type?
            .GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Cast<MemberInfo>()
            .Concat(type.GetFields(BindingFlags.Instance | BindingFlags.Public))
            .Where(x => !x.GetCustomAttributes<JsonIgnoreAttribute>().Any())
            ?? Array.Empty<Type>();
    }
}

Benchmarks

The following benchmarks are showing the differences between converting from dictionary to instance and from instance to dictionary. SPOILER: You get the best efficiency with the DefaultResolver.

Test environment

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 8 physical cores
.NET Core SDK=3.0.100
  [Host]   : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
  ShortRun : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT 

Convert to dictionary

Method N Mean Error StdDev Ratio RatioSD Rank Gen 0 Gen 1 Gen 2 Allocated
DefaultResolver 1 6.277 us 12.242 us 0.6710 us 1.00 0.00 1 0.5875 - - 1.81 KB
DataContractResolver 1 16.106 us 18.827 us 1.0320 us 2.59 0.35 3 0.9918 - - 3.07 KB
DataContractResolver-IgnoreAncestors 1 12.773 us 8.038 us 0.4406 us 2.05 0.15 2 0.9766 - - 3.07 KB
JsonNetResolver 1 50.861 us 56.199 us 3.0805 us 8.14 0.56 4 5.8594 - - 18 KB
DefaultResolver 10 5.572 us 1.225 us 0.0672 us 1.00 0.00 1 0.5875 - - 1.81 KB
DataContractResolver 10 14.726 us 33.944 us 1.8606 us 2.64 0.32 3 0.9918 - - 3.07 KB
DataContractResolver-IgnoreAncestors 10 12.287 us 1.493 us 0.0818 us 2.21 0.03 2 0.9918 - - 3.07 KB
JsonNetResolver 10 52.918 us 89.842 us 4.9246 us 9.50 1.00 4 5.8594 - - 18 KB
DefaultResolver 100 6.063 us 4.733 us 0.2595 us 1.00 0.00 1 0.5875 - - 1.81 KB
DataContractResolver 100 12.419 us 4.004 us 0.2195 us 2.05 0.06 2 0.9918 - - 3.07 KB
DataContractResolver-IgnoreAncestors 100 12.413 us 13.096 us 0.7179 us 2.05 0.20 2 0.9918 - - 3.07 KB
JsonNetResolver 100 54.870 us 36.022 us 1.9745 us 9.06 0.50 3 5.8594 - - 18 KB

Convert to instance

Method N Mean Error StdDev Ratio RatioSD Rank Gen 0 Gen 1 Gen 2 Allocated
DefaultResolver 1 10.76 us 0.491 us 0.027 us 1.00 0.00 1 0.7019 - - 2.18 KB
DataContractResolver 1 53.33 us 61.631 us 3.378 us 4.96 0.32 3 3.7842 - - 11.72 KB
DataContractResolver-IgnoreAncestors 1 54.74 us 99.851 us 5.473 us 5.09 0.51 4 3.7842 - - 11.72 KB
JsonNetResolver 1 161.86 us 94.736 us 5.193 us 15.05 0.46 5 16.6016 - - 51.52 KB
PureJsonNet 1 18.55 us 24.079 us 1.320 us 1.72 0.12 2 2.4414 - - 7.49 KB
DefaultResolver 10 11.64 us 18.704 us 1.025 us 1.00 0.00 1 0.7019 - - 2.18 KB
DataContractResolver 10 64.32 us 118.677 us 6.505 us 5.53 0.42 3 3.7842 - - 11.72 KB
DataContractResolver-IgnoreAncestors 10 54.44 us 22.665 us 1.242 us 4.70 0.40 2 3.7842 - - 11.72 KB
JsonNetResolver 10 169.81 us 208.025 us 11.403 us 14.66 1.68 5 16.6016 - - 51.52 KB
PureJsonNet 10 163.40 us 185.507 us 10.168 us 14.10 1.48 4 11.2305 - - 35.09 KB
DefaultResolver 100 13.51 us 13.977 us 0.766 us 1.00 0.00 1 0.7019 - - 2.18 KB
DataContractResolver 100 64.19 us 64.332 us 3.526 us 4.76 0.36 3 3.7842 - - 11.72 KB
DataContractResolver-IgnoreAncestors 100 56.80 us 92.891 us 5.092 us 4.20 0.28 2 3.7842 - - 11.72 KB
JsonNetResolver 100 138.36 us 34.188 us 1.874 us 10.26 0.44 4 16.6016 - - 51.52 KB
PureJsonNet 100 1,858.79 us 6,022.705 us 330.125 us 137.79 24.91 5 93.7500 - - 292.02 KB

Open Source License Acknowledgements and Third-Party Copyrights

extensions.dictionary's People

Contributors

dependabot[bot] avatar siberaindustries avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

extensions.dictionary's Issues

Nested dictionary support

Nested dictionaries of type IDictionary<string, object> are currently not supported when converting back to an instance (converting from instance to dictionary is working as expected)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.