Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Saturday 19 March 2022

Using C# 9 language features in .NET Framework and .NET Standard projects

C# 7.0 came out in March 2017 and Microsoft has published other frameworks later, such as .NET Core and .NET 5 plus .NET 6. If you are working with a .NET Framework based solution (or .NET Standard 2.0), you can actually get support for C# 8 and C# 9 language version - enabling you to utilize more of C# language features. The following steps can be used to enable C# language 9 in for example .NET Framework 4.8 (tested and verified that I could use records (a C# 9 language feature).
  • Specify in the .csproj file(s) that you want to use <LangVersion> element set to 9.0
  • Consider using a file called Directory.Build.props (at the root level of your solution) (Case sensitive on Linux) with this shared setting to enabled C# 9.0 version in all projects.
  • Using C# 9 language version also requires you to include a small file in each project listed below, call it IsExternalInitPatch.cs for example.
File IsExternalInitPatch.cs should include this :

  
namespace System.Runtime.CompilerServices
{
    internal static class IsExternalInit { }
}
  


Now you can start playing around with C# 9 in a .NET Framework 4.8 solution for example, which earlier has been limited to C# 7.1 and no later language version features of C#.

namespace SomeAcme.SomeProduct.Common.Test
{
    /// <summary>
    /// This is just a test of csharp 9 for SomeAcme.SomeProduct
    /// Note that Directory.Build.props in this branch uses LangVersion set to 9.0 and we need the file IsExternalInit.cs in every project
    /// </summary>
    /// <remarks>
    /// See these two urls: 
    /// https://btburnett.com/csharp/2020/12/11/csharp-9-records-and-init-only-setters-without-dotnet5.html
    /// https://blog.ndepend.com/using-c9-record-and-init-property-in-your-net-framework-4-x-net-standard-and-net-core-projects/
    /// </remarks>
    [TestFixture]
    public class TestOutCsharpNine
    {

        public record Operasjon (DateTime StartTid, bool ErElektiv, string PasientNavn);


        [Test]
        public void Test_Records_ChsharpNine_And_Deconstruction_And_Discardable_Variables()
        {
            var op = new Operasjon(DateTime.Today.AddHours(8).AddMinutes(15), true, "Bjarne Brøndbo");
            (_, _, string pasientNavn) = op;
            pasientNavn.Should().Be(op.PasientNavn);
        }

        [Test]
        public void Test_Init_Only_Props()
        {
            var op = new OperasjonWithInitOnlyProps
            {
                ErElektiv = true,
                PasientNavn = "Thomas Brøndbo"
            };
            // op.PasientNavn = "foo"; 
            //uncommenting line above should demonstrate init only property giving compiller error if trying to mutate or alter this property
            op.PasientNavn.Should().Contain("Brøndbo");
        }

        [DataContract]
        public class OperasjonWithInitOnlyProps
        {
            [DataMember]
            public string PasientNavn { get; init; }
            [DataMember]
            public bool ErElektiv { get; init; }
        }
    }
}


The CSharp compiler sets up default the CSharp language features according to these rules: The compiler determines a default based on these rules:
Target framework	version	C# language version default
.NET	6.x	C# 10
.NET	5.x	C# 9.0
.NET Core	3.x	C# 8.0
.NET Core	2.x	C# 7.3
.NET Standard	2.1	C# 8.0
.NET Standard	2.0	C# 7.3
.NET Standard	1.x	C# 7.3
.NET Framework	all	C# 7.3
So .NET Framework and .NET Standard based solution has not gotten per default any modernization of C# sharp features since March 2017 (five years ago), but we can with some small modification still use C# 9.0 which came out 1.5 years ago. Of course, this C# language version is meant to be used with .NET 5, so do not expect everything to be supported on it. However, chances are high that much of C# 8 and C# 9 language features could be handy to use in many .NET Framework and .NET Standard based projects. For example, records with their support for immutability is definately a big new thing in C# compared to what is avilable in C# language version 8 or earlier. Lastly, you must also consider how to build C# 9 language features (which assumes .NET 5 available) on a build server. For Team City for example, you must install .NET 5 SDK on the build agent.
Also, most likely you have for example a MS Build step in Team City, so you should use MS Build 16 (VS 2019 Build tools) and install the build tools for VS 2019 on the build agent from this url or google for Build Tools for VS 2019: https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16&src=myvs&utm_medium=microsoft&utm_source=my.visualstudio.com&utm_campaign=download&utm_content=vs+buildtools+2019 For Azure Devops, choose the VS 2022 agent. I still had to add a "Use NET Core" task and choose 'Package to install' set to 'SDK (contains runtime)', the YAML looks like this:

steps:
- task: UseDotNet@2
  displayName: 'Use .NET Core sdk 5.0.100'
  inputs:
    version: 5.0.100
    includePreviewVersions: true

Also note this - albeit you might have .NET Framework 4.8 in a project, your config file like app.config might have this :
 
  


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
	<appSettings>
 
 
The supportedRuntime might force you to in a specific project to have a LangVersion set to a lower value anyways. So you might need for example to have LangVersion set to 7.1 in one project and default to LangVersion 9.0. To sum up :
  • .NET Framework and .NET Standard can still use C# language version 8 or 9. You need to do the adjustments I mentioned in this article.
  • C# language version 10 is only supported by .NET 6. To use this language version you have to upgrade framework..
  • Also - test out new language features in one project first and use the basic features first. If you use advanced language features of C# language version 8 or 9 you might consider some glitches.. However, you should get a compiler warning for most errors you encounter.
  • Don't forget that your build agent must be able to build the solution too. So you can use VS 2022 hosted agent and consider also the USE NET Core Sdk task I mentioned here if you build in Azure Devops. If you use a self-hosted agent, like Team City on-premises build agent, you need to install the newest VS 2019 SDK / Build Tools to ensure that you have the C# langversion.
In the Developer command prompt on the build agent you can run this command
 
  csc -langversion:? 
 
This should output the langversions of C# your build agent supports. It also works on a developer PC (use the VS 2019 command prompt). As I noted, C# 10 is only supported in .NET 6. We might have a future situation where C# 11 is still supported in a .NET 6 solution - I am not sure what Microsoft is planning here. But for other and earlier frameworks, it looks like C# 9 is the end of the road of language versions - we have to upgrade to .NET 6 to utilize newer language features (or consider dragging in Nuget compiler packages ..)

Saturday 12 June 2021

Concepts of a simple draw ink control in Windows Forms

This article will present a simple draw ink control in Windows Forms. The code is run in Linqpad and the concepts here should be easily portable to a little application. Note - there is already built in controls for Windows Forms for this (and WPF and UWP too). That is not the point of this article. The point is to display how you can use System.Reactive and Observable.FromEventPattern method to create an event source stream from
CLR events so you can build reactive applications where the source pushes updates to its target / receiver instead of traditional pull based scenario of event subscriptions. First off, we install Linqpad from: https://www.linqpad.net I used Linqpad 5 for this code, you can of course download Linqpad 6 with .Net core support, but this article is tailored for Linpad 5 and .NET Framework. After installing Linqpad 5, start it and hit F4. Choose Add Nuget. Now choose Search online and type the following four nuget packages to get started with Reactive extensions for .NET.
  • System.Reactive
  • System.Reactive.Core
  • System.Reactive.Interfaces
  • System.Reactive.Linq
Also choose Add.. and choose System.Windows.Forms. Also, choose the tab Additional Namespace Imports. Import these namespaces
  • System.Reactive
  • System.Reactive.Linq
  • System.Windows.Forms
Over to the code, first we create a Form with a PictureBox to draw onto like this in C# program:


void Main()
{
	var form = new Form();
	form.Width = 800;
	form.Height = 800;
	form.BackColor = Color.White;
	
	var canvas = new PictureBox();
	canvas.Height = 400;
	canvas.Width = 400;
	canvas.BackColor = Color.AliceBlue;
	form.Controls.Add(canvas);
    .. //more code soon


Next up we create a list of Point to add the points to. We also use Observable.FromEventPattern to track events using the System.Reactive method to create an observable from a CLR event. We then subscribe to the three events we have set up with observables and add the logic to draw anti-aliased Bezier curves. Actually, drawing a Bezier curve usually consists of the end user defining four control points, the start and end of the bezier line and two control points (for the simplest Bezier curve). However, I chose anti-aliased Bezier curves that just uses the last four points from the dragged line, since smooth Bezier curves looks way better than using DrawLine for example for simple polylines. I use GDI CreateGraphics() method of the Picturebox (this is also available on most other Windows Forms controls, including Forms, but I wanted to have the drawing restricted to the PictureBox). The full code then is the entire code snippet below:
 
 void Main()
{
	var form = new Form { Width = 800, Height = 800, BackColor = Color.White };
	var canvas = new PictureBox { Height = 400, Width = 400, BackColor = Color.AliceBlue };
	form.Controls.Add(canvas);	
    var points = new List<Point>();
	bool isDrag = false;	
	var mouseDowns = Observable.FromEventPattern<MouseEventArgs>(canvas, "MouseDown");
	var mouseUps = Observable.FromEventPattern<MouseEventArgs>(canvas, "MouseUp");
	var mouseMoves = Observable.FromEventPattern<MouseEventArgs>(canvas, "MouseMove");
	mouseDowns.Subscribe(m =>
	{
		if (m.EventArgs.Button == MouseButtons.Right)
		{
			isDrag = false;
			points.Clear();
			canvas.CreateGraphics().Clear(Color.AliceBlue);
			return;
		}
	 isDrag = true;	 
	});	
	mouseUps.Subscribe(m => {
		isDrag = false;
	});	
	mouseMoves.Subscribe(move =>  {
	 points.Add(new Point(move.EventArgs.Location.X, move.EventArgs.Location.Y));
	 if (isDrag && points.Count > 4) {
			//form.CreateGraphics().DrawLine(new Pen(Color.Blue, 10), points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y);
			var pt1 = new PointF(points[points.Count - 4].X, points[points.Count - 4].Y);
			var pt2 = new PointF(points[points.Count - 3].X, points[points.Count - 3].Y);
			var pt3 = new PointF(points[points.Count - 2].X, points[points.Count - 2].Y);
			var pt4 = new PointF(points[points.Count - 1].X, points[points.Count - 1].Y);			
			var graphics = canvas.CreateGraphics();
			graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
			graphics.DrawBezier(new Pen(Color.Blue, 4.0f), pt1, pt2, pt3, pt4);			
		}		
	});	
	form.Show();
}


 
Linqpad/System.Reactive/GDI Windows Forms in action ! Screenshot:

I have added comments here for defining a polyline also instead of Bezier, since this also works and is quicker than the nicer Bezier curve. Maybe you want to display this on a simple device with less processing power etc. To clear the line, just hit right click button. To start drawing, just left click and drag and let go again. Now look how easy this code really is to create a simple Ink control in Windows Forms ! Of course Windows Forms today are more and more "dated" compared to younger frameworks, but it still does its job. WPF got its own built-in InkControl. But in case you want an Ink control in Windows Forms, this is an easy way of creating one and also a good Hello World to Reactive extensions. In .NET Core, the code should be really similar to the code above. Windows Forms is available with .NET Core 3.0 or newer. https://devblogs.microsoft.com/dotnet/windows-forms-designer-for-net-core-released/

Sunday 27 September 2020

Generic Memory Cache for .Net Framework

The following sample code shows how to create a Generic Memory Cache for .Net Framework. This allows you to cache specific items defined by a TCacheItemData type argument, i.e. caching same type of data such as instances of a class, or arrays of instances. Inside your .csproj you should see something like:
    
Over to the implementation. Since a memory cache is shared by possibly other applications, it is important to prefix your cached contents, i.e. prefix the the keys. This makes it easier to barrier the memory cache. Note though that some barriering is done accross processes of course, this is just to make it easier within your application and running process to group the cached elements with a prefix key used for the generic memory cache operations. Now over to the implementation.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Caching;

namespace SomeAcme.SomeUtilNamespace
{
    /// <summary>
    /// Thread safe memory cache for generic use
    /// </summary>
    /// <typeparam name="TCacheItemData">Payload to store in the memory cache</typeparam>
    /// <remarks>Uses MemoryCache.Default which defaults to an in-memory cache. All cache items are prefixed with an 'import cache session guid' to compartmentalize
    /// multiple paralell importing sessions</remarks>
    public class GenericMemoryCache<TCacheItemData> where TCacheItemData : class
    {
        private readonly string _prefixKey;
        private readonly ObjectCache _cache;
        private readonly CacheItemPolicy _cacheItemPolicy;

        public GenericMemoryCache(string prefixKey, int defaultExpirationInSeconds = 0)
        {
            defaultExpirationInSeconds = Math.Abs(defaultExpirationInSeconds); //checking if a negative value was passed into the constructor.

            _prefixKey = prefixKey;
            _cache = MemoryCache.Default;
            _cacheItemPolicy = defaultExpirationInSeconds == 0
                ? new CacheItemPolicy { Priority = CacheItemPriority.NotRemovable }
                : new CacheItemPolicy
                { AbsoluteExpiration = DateTime.Now.AddSeconds(Math.Abs(defaultExpirationInSeconds)) };
        }

        /// <summary>
        /// Cache object if direct access is desired
        /// </summary>
        public ObjectCache Cache => _cache;

        public string PrefixKey(string key) => $"{_prefixKey}_{key}";


        /// <summary>
        /// Adds an item to memory cache
        /// </summary>
        /// <param name="key"></param>
        /// <param name="itemToCache"></param>
        /// <returns></returns>
        public bool AddItem(string key, TCacheItemData itemToCache)
        {
            try
            {
                if (!key.StartsWith(_prefixKey))
                    key = PrefixKey(key);

                var cacheItem = new CacheItem(key, itemToCache);
                _cache.Add(cacheItem, _cacheItemPolicy);
                return true;
            }
            catch (Exception err)
            {
                Debug.WriteLine(err);
                return false;
            }
        }

        public virtual List<T> GetValues<T>()
        {
            List<T> list = new List<T>();
            IDictionaryEnumerator cacheEnumerator = (IDictionaryEnumerator)((IEnumerable)_cache).GetEnumerator();

            while (cacheEnumerator.MoveNext())
            {
                if (cacheEnumerator.Key == null)
                    continue;
                if (cacheEnumerator.Key.ToString().StartsWith(_prefixKey))
                    list.Add((T)cacheEnumerator.Value);
            }
            return list;
        }

        /// <summary>
        /// Retrieves a cache item. Possible to set the expiration of the cache item in seconds. 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TCacheItemData GetItem(string key)
        {
            try
            {
                if (!key.StartsWith(_prefixKey))
                    key = PrefixKey(key);
                if (_cache.Contains(key))
                {
                    CacheItem cacheItem = _cache.GetCacheItem(key);
                    object cacheItemValue = cacheItem?.Value;
                    UpdateItem(key, cacheItemValue as TCacheItemData);
                    TCacheItemData item = _cache.Get(key) as TCacheItemData;
                    return item;
                }
                return null;
            }
            catch (Exception err)
            {
                Debug.WriteLine(err);
                return null;
            }
        }

        public bool SetItem(string key, TCacheItemData itemToCache)
        {
            try
            {
                if (!key.StartsWith(_prefixKey))
                    key = PrefixKey(key);
                if (GetItem(key) != null)
                {
                    AddItem(key, itemToCache);
                    return true;
                }

                UpdateItem(key, itemToCache);
                return true;
            }
            catch (Exception err)
            {
                Debug.WriteLine(err);
                return false;
            }
        }


        /// <summary>
        /// Updates an item in the cache and set the expiration of the cache item 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="itemToCache"></param>
        /// <returns></returns>
        public bool UpdateItem(string key, TCacheItemData itemToCache)
        {
            if (!key.StartsWith(_prefixKey))
                key = PrefixKey(key);
            CacheItem cacheItem = _cache.GetCacheItem(key);
            if (cacheItem != null)
            {
                cacheItem.Value = itemToCache;
                _cache.Set(key, itemToCache, _cacheItemPolicy);
            }
            else
            {
                //if we cant find the cache item, just set the cache directly
                _cache.Set(key, itemToCache, _cacheItemPolicy);

            }
              return true;
           
        }

        /// <summary>
        /// Removes an item from the cache 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveItem(string key)
        {
            if (!key.StartsWith(_prefixKey))
                key = PrefixKey(key);

            if (_cache.Contains(key))
            {
                _cache.Remove(key);
                return true;
            }
            return false;
        }

        public void AddItems(Dictionary<string, TCacheItemData> itemsToCache)
        {
            foreach (var kvp in itemsToCache)
                AddItem(kvp.Key, kvp.Value);
        }

        /// <summary>
        /// Clear all cache keys starting with known prefix passed into the constructor.
        /// </summary>
        public void ClearAll()
        {
            var cacheKeys = _cache.Select(kvp => kvp.Key).ToList();
            foreach (string cacheKey in cacheKeys)
            {
                if (cacheKey.StartsWith(_prefixKey))
                    _cache.Remove(cacheKey);
            }
        }

    }
}




Wednesday 17 June 2020

Multiple enum values set to same value codefix for VS

I created a new extension in Visual Studio today! The UniqueEnumValueFixer vs extension is now available here! https://marketplace.visualstudio.com/items?itemName=ToreAurstadIT.EXT001 The extension is actually a Code Fix for Visual Studio. It flags a warning to the developer if an enum contains multiple members mapped to the same value. Having a collision with values for enum causes ambiguity and confusion for the developer. An enum value has not got a single mapping from enum member to integer value. Example like this: Here we see that iceconverted is set to Fudge, which is the last of the colliding valued enum members. This gives code which is not clear and confusing and ambiguous. It is perfectly valid, but programmers will perhaps sigh a bit when they see enums with multiple members mapped to same value. The following sample code shows a violation of the rule:

    enum IceCream
    {
        Vanilla = 0, 
        Chocolate = 2,
        Strawberry = Vanilla,
        Peach = 2
    }

Here, multiple members are mapped to the same value in the enum. Strawberry and Vanilla points to the same value through assignment. And Peach is set to same value as Chocolate. The code fix will show enums containing the violation after compiling the solution in the Errors and Warnings pane of Visual Studio.

   public override void Initialize(AnalysisContext context)
        {
            // TODO: Consider registering other actions that act on syntax instead of or in addition to symbols
            // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information
            context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);

        }

        private static void AnalyzeSymbol(SymbolAnalysisContext context)
        {
            try
            {
                var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;
                if (namedTypeSymbol.EnumUnderlyingType != null)
                {
                    var valueListForEnum = new List<Tuple<string, int>>();
                    //Debugger.Launch();
                    //Debugger.Break();
                    var typeResolved = context.Compilation.GetTypeByMetadataName(namedTypeSymbol.MetadataName) ?? context.Compilation.GetTypeByMetadataName(namedTypeSymbol.ToString());
                    if (typeResolved != null)
                    {
                        foreach (var member in typeResolved.GetMembers())
                        {
                            var c = member.GetType().GetRuntimeProperty("ConstantValue");
                            if (c == null)
                            {
                                c = member.GetType().GetRuntimeProperties().FirstOrDefault(prop =>
                                    prop != null && prop.Name != null &&
                                    prop.Name.Contains("IFieldSymbol.ConstantValue"));
                                if (c == null)
                                {
                                    continue;
                                }
                            }

                            var v = c.GetValue(member) as int?;
                            if (v.HasValue)
                            {
                                valueListForEnum.Add(new Tuple<string, int>(member.Name, v.Value));
                            }
                        }
                        if (valueListForEnum.GroupBy(v => v.Item2).Any(g => g.Count() > 1))
                        {
                            var diagnostic = Diagnostic.Create(Rule, namedTypeSymbol.Locations[0],
                                namedTypeSymbol.Name);
                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                }
            }
            catch (Exception err)
            {
                Console.WriteLine(err);
            }

        }

The source code is available on Github here: https://github.com/toreaurstadboss/UniqueEnumValuesAnalyzer

Friday 28 February 2020

Strongly typed ConfigurationManager in .NET Framework

Handling configuration files in .NET Framework is often tedious. You retrieve the app setting as a string and must then parse it out. Dont you wish we could have a generic method to get a strongly typed app setting instead and spare ourselves with some code ? Sure you can!

using System;
using System.ComponentModel;
using System.Configuration;

namespace Hemit.OpPlan.Common.Extensions
{

    /// <summary>
    /// Utility methods for ConfigurationManager. Also included methods for handling OpenExeConfiguration (running process configuration, for example in tests and installers)
    /// </summary>
    public static class ConfigurationManagerWrapper
    {
        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static void SetAppsettingForExecConfiguration(string appsetting, object value)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings[appsetting].Value = Convert.ToString(value);
            config.Save(ConfigurationSaveMode.Modified);
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static string GetAppsettingExecConfiguration(string appsetting, object value)
        {
            return ConfigurationManager.AppSettings[appsetting];
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static void SetAppsettingForConfiguration(string appsetting, object value)
        {
            ConfigurationManager.AppSettings[appsetting] = Convert.ToString(value);
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static string GetAppsettingForExecConfiguration(string appsetting, object value)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            return config.AppSettings.Settings[appsetting].Value;
        }


        /// <summary>
        /// Use this extension method to get a strongly typed app setting from the configuration file.
        /// Returns app setting in configuration file if key found and tries to convert the value to a specified type. In case this fails, the fallback value
        /// or if NOT specified - default value - of the app setting is returned
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="appsettingKey"></param>
        /// <param name="fallback"></param>
        /// <returns></returns>
        public static T GetAppsetting<T>(string appsettingKey, T fallback = default(T))
        {
            string val = ConfigurationManager.AppSettings[appsettingKey] ?? "";
            if (!string.IsNullOrEmpty(val))
            {
                try
                {
                    Type typeDefault = typeof(T);
                    var converter = TypeDescriptor.GetConverter(typeof(T));
                    return converter.CanConvertFrom(typeof(string)) ? (T)converter.ConvertFrom(val) : fallback;
                }
                catch (Exception err)
                {
                    Console.WriteLine(err); //Swallow exception
                    return fallback;
                }
            }
            return fallback;
        }

    }
}



Thursday 20 February 2020

Generic method ShouldAll for FluentAssertions

This is a simple etension method for Fluent Assertions called ShouldAll that can be run on a collection and you can pass in your predicate of your choice and see the output. Consider this unit test:


         var oneyearPeriodComparions = new []
            {
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2017 , CalculatedPeriod = calculatedReportPeriod2017.First() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2017 , CalculatedPeriod = calculatedReportPeriod2017.Last()},
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2018 , CalculatedPeriod = calculatedReportPeriod2018.First()},
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2018 , CalculatedPeriod = calculatedReportPeriod2018.Last() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2019 , CalculatedPeriod = calculatedReportPeriod2019.First() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2019 , CalculatedPeriod = calculatedReportPeriod2019.Last() }
            };

            oneyearPeriodComparions.ShouldAll(comparison => comparison.CalculatedPeriod.ReportPeriodStartDateAndEndDateIsEqualTo(comparison.ReferencePeriod), outputPassingTests:true);


This uses this extension test for Fluent Assertions:

using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace SomeAcme.SomeLib
{

    public static class FluentAssertionsExtensions
    {

        /// <summary>
        /// Inspects that all tests are passing for given collection and given predicate
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instances"></param>
        /// <param name="predicate"></param>
        /// <param name="outputFailingTests"></param>
        public static void ShouldAll<T>(this IEnumerable<T> instances, Expression<Func<T, bool>> predicate, bool outputFailingTests = true, bool outputPassingTests = false)
        {
            foreach (var instance in instances)
            {
                var isTestPassing = predicate.Compile().Invoke(instance);
                if (!isTestPassing && outputFailingTests || outputPassingTests)
                    Console.WriteLine($@"Test Running against object: {instance} Test Pass?:{isTestPassing}");
                isTestPassing.Should().Be(true);
            }
        }
    }

}


Sunday 22 September 2019

Looking into (circular) dependencies of MEF using C# and Ndepend - Migrating from MEF to Autofac

I decided to look into circular dependencies in C# using reflection and NDepend today. A circular dependency is problematic, especially if you are using dependency injection. In fact, if your system injects dependencies through constructors, if part A imports part B and vice versa - you will usually get a crash. To instantiate the part A we need part B, but that holds also for part A instantiating part B. A huge system I have been working on for years uses MEF or Managed Extensibility Framework. This is primarily an extension framework for allowing pluggable applications, such as seen in Silverlight. It also provides Inversion of Control and you can also import through constructors, that is - every type can decorate one constructor with the [ImportingConstructor] attribute. My system however uses property based injection. You can decorate a property with [Import] attribute and the type of the constructor will then create an instance of an object exporting itself as that type. You can import either concrete or interface based types, and it is also possible to specify a key for the import (string identifier). So the bad part about property based injections is that circular injections can creep up on you - the system will not crash - but it allows circular depedendencies to exist in your system. I created the following Unit Test to detect these circular dependencies.
        [Test]
        [Category(TestCategories.IntegrationTest)]
        public void OutputCircularDependencies()
        {
            var compositionParts = new List>CompositionPart<();
          
            foreach (var part in _aggregateCatalog.Parts)
            {
                var importList = new List>string<();
               
                foreach (var import in part.ImportDefinitions)
                {
                    if (import != null)
                    {
                        importList.Add(import.ContractName);
                    }
                }

                foreach (var export in part.ExportDefinitions)
                {
                    string exportType = null;
                    if (export.Metadata.ContainsKey("ExportTypeIdentity"))
                        exportType = export.Metadata["ExportTypeIdentity"].ToString();

                    string creationPolicy = null;
                    if (export.Metadata.ContainsKey("System.ComponentModel.Composition.CreationPolicy"))
                        creationPolicy = export.Metadata["System.ComponentModel.Composition.CreationPolicy"].ToString();
                    compositionParts.Add(new CompositionPart(part.ToString(), exportType, creationPolicy, importList));                   
                }             
            }

            foreach (var part in compositionParts)
            {
                //check each import if it imports this part
                foreach (var importPart in part.Imports)
                {
                    var matchingPart = compositionParts.FirstOrDefault(c =< c.Identity == importPart);
                    if (matchingPart != null)
                    {
                        if (matchingPart.Imports.Any(i =< i == part.Identity))
                        {
                            //Circular reference detected!
                            Console.WriteLine(@"Component {0} is circular dependent of component {1}", part.Name, matchingPart.Name);
                        }
                    }
                }
            }

            
        }
The code loops through the ComposablePart parts of the AggregateCatalog.Each part has ExportDefinitions (usually one export) and ImportDefinitions (often multiple imports). The first pass will then just gather up information for all the parts of the AssemblyCatalog and then loop through each part again and loop though its imports in an inner loop. If the imported part imports the part itself, we have a circular dpeendency. The test just outputs the circular dependencies to the console. I use the class CompositionPart to have a entity to contain some information about each composition part of the AssemblyCatalag instance. It is just a regular AssemblyCatalog in MEF, created like this:

        readonly AggregateCatalog _aggregateCatalog = new AggregateCatalog();
        CompositionContainer _container;

        [SetUp]
        public void CommonInitialize()
        {
            _aggregateCatalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetAssembly(typeof(SomeFeatureModule))));
            _aggregateCatalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetAssembly(typeof(SomeFeatureServiceAgent))));
            _aggregateCatalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetAssembly(typeof(SomeCommonUtil))));
            _aggregateCatalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetAssembly(typeof(SomeProvider))));           
            _container = new CompositionContainer(_aggregateCatalog);
            _container.ComposeParts();
        }

As we can see, the AggregateCatalog just consists of several assemblies in .NET. I rewrite the software to not use MEF and property based imports (i.e. properties decorated with the import attribute of System.ComponentModel.Composition.ImportAttribute) by looping through the parts of the AggregateCatalog and looking at the export definitions. The target is Autofac, which is a DI framework that offers dependency injection IMHO better than MEF ImportingConstructor, so analyzing the export defiitions, I can create a list of statements to migrate from MEF to Autofac.

        [Test]
        [Category(TestCategories.IntegrationTest)]
        public void OutputAutofacRegistrations()
        {

            var sb = new StringBuilder();

            foreach (var part in _aggregateCatalog.Parts)
            {
                string partName = part.ToString();

                if (part.ExportDefinitions != null)
                {
                    foreach (var export in part.ExportDefinitions)
                    {
                        string exportType = null;
                        if (export.Metadata.ContainsKey("ExportTypeIdentity"))
                             exportType = export.Metadata["ExportTypeIdentity"].ToString();                        
                        
                        string creationPolicy = null;
                        if (export.Metadata.ContainsKey("System.ComponentModel.Composition.CreationPolicy"))
                            creationPolicy = export.Metadata["System.ComponentModel.Composition.CreationPolicy"].ToString();
                        
                        string autofacExportDefinition = string.Format("builder.RegisterType>{0}<(){1}{2};", partName, 
                            !string.IsNullOrEmpty(exportType) ? ".As>" + exportType + "<()" : string.Empty,
                            !string.IsNullOrEmpty(creationPolicy) && creationPolicy.ToLower().Contains("nonshared") ? 
                            ".InstancePerDependency()" : ".SingleInstance()");
                        sb.AppendLine(autofacExportDefinition);

                        Console.WriteLine(autofacExportDefinition);
                    }
                    
                }

            }

I also used Ndepend as a supporting tool to look at visualizations of these dependencies. I had trouble detecting ImportingAttribute on properties (properties are methods in C# known as 'property getters' and 'property setters'), but at least I came up with the following CQLinq statements to look for all types that are decorated with the ExportAttribute (exporting parts) and Ndepend then got nice visualization of something called 'View internal dependency cycles on graph'. As Ndepend or my CQLinq skills lacking could not find the importing attribute decorated on properties (Ndepend does not fully support attribute detection on methods in an easy way yet - detecting attributes on types is easier), I ended up with the CQLinq below to at least list up the exporting classes and launching the graphical tool to look if the parts (classes) with circular dependencies was a hotspot in the source base, i.e. a class used by many other classes. The CQLinq below shows how to generate such a graph for revealing class interdepenencies - quite easy using Ndepend.
let exportingTypes = from type in JustMyCode.Types
where type.IsClass && type.HasAttribute("System.ComponentModel.Composition.ExportAttribute")
&& (type.FullNameLike("SomeAcme"))
let f = Types.ChildMethods().Where(m =< m.IsPropertyGetter)
select type
let typesAttributes = Types
from m in exportingTypes.UsingAny(typesAttributes).ChildMethods().Where(x =< x.IsPropertySetter || x.IsPropertyGetter)
let mAttributes = typesAttributes.Where(t =< m.HasAttribute(t)).ToArray()
where mAttributes .Length < 0
select new { m, mAttributes} 
So there you have some tips around how to migrate from MEF to Autofac and detect cyclic dependencies in your source code. Ndepend will be a good tool to have as a companion to the refactoring job when you want to migrate. I will suggest to first rewrite your application using importing constructors instead of property based imports and then fix up the cyclic dependencies. You can use the Lazy initializer for example. It will delay constructing a part of type T specified to fix up such circular dependencies. Or you could of course refactor the code such that part A and part B that imports eachother instead imports some other part C both.. There are different ways to fix it up. Once you have rewritten the software to use importing constructors and there are no circular dependencies, you can switch to Autofac. I showed you in the unit test OutputAutofacRegistrations how to do that. It outputs ContainerBuilder statements to build up a working Autofac IContainer with same kind of mesh of dependencies as in the MEF based application.

Thursday 1 August 2019

Consistency guard of enums used in Entity Framework

This is a consistency guard for enums in Entity Framework. It is a mechanism for protecting an entity in Entity Framework or just EF, in case an enum value was loaded from the database with an illeagal value. An illeagal enum value would be any value of an enum that cannot be parsed into an enum. We use Enum.IsDefined method (at first running Convert.ChangeType) to check if the value for the enum is leagal or not. We define a helper class BrokenEnumValue to contain our metadata about enum values that are illeagal or 'broken'. The rest of the code in this article goes into the DbContext class (Or ObjectContext would also work) that EF uses. The ObjectMaterialized event is added in the constructor for example.
            var objectContext = ((IObjectContextAdapter) this).ObjectContext;
            _log = (ILog) AutofacHostFactory.Container.Resolve(typeof(ILog));
            objectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized;
Our helper POCO:

    public class BrokenEnumValue
    {
        public string PropertyName { get; set; }
        public string PropertyTypeName { get; set; }
        public Guid? SchemaGuid { get; set; }
        public string OldValue { get; set; }
        public string CorrectedValue { get; set; }

        public override string ToString()
        {
            return $"{PropertyName} {PropertyTypeName} {SchemaGuid} {OldValue} {CorrectedValue}";
        }
    }



        private void ObjectContext_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
        {
            var brokenEnumProperties = FixBrokenEnumProperties(e.Entity);
            if (brokenEnumProperties.Any())
            {
                Type objType = e.Entity.GetType();
                var idProperty = objType.GetProperty("Id");
                Guid? schemaGuid = idProperty?.GetValue(e.Entity, null) as Guid?;
                foreach (var brokenEnum in brokenEnumProperties)
                    brokenEnum.SchemaGuid = schemaGuid;
                string brokenEnumsInfo = string.Join(" ", brokenEnumProperties.Select(b => b.ToString()).ToArray());
                _log.WriteWarning($"Detected broken enum propert(ies) in entity and resolved them to default value if available in enum (None): {brokenEnumsInfo}");
            }
        }

           public IList<BrokenEnumValue> FixBrokenEnumProperties(object obj)
        {
            var list = new List<BrokenEnumValue>();
            try
            {
                if (obj == null) return list;
       
                PropertyInfo[] properties = obj.GetType().GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    if (property.GetIndexParameters()?.Any() == true)
                        continue; //skip indexer properties
                    if (property.PropertyType.IsArray)
                    {
                        Array a = (Array) property.GetValue(obj);
                        for (int i = 0; i < a.Length; i++)
                        {
                            object o = a.GetValue(i);
                            list.AddRange(FixBrokenEnumProperties(o));
                        }
                        continue; //continue to next iteration
                    }
                    object propValue = property.GetValue(obj, null);
                    var elems = propValue as IList;
                    if (elems != null)
                    {
                        foreach (var item in elems)
                        {
                            list.AddRange(FixBrokenEnumProperties(item));
                        }
                    }
                    else
                    {
                        if (property.PropertyType.IsEnum && !IsEnumDefined(propValue, property.PropertyType))
                        {
                            var correctedValue = GetDefaultEnumValue(propValue, property.PropertyType);
                            list.Add(new BrokenEnumValue
                            {
                                CorrectedValue = correctedValue?.ToString(),
                                OldValue = propValue?.ToString(),
                                PropertyName = property.Name,
                                PropertyTypeName = property.PropertyType.FullName,
                            });
                            property.SetValue(obj, correctedValue);
                            
                        }
                        if (property.PropertyType.IsClass && (property.PropertyType.GetCustomAttributes(typeof(DataContractAttribute))?.Any() == true)
                                                          && !(property.PropertyType == typeof(string)) && !property.PropertyType.IsValueType)
                        {
                            list.AddRange(FixBrokenEnumProperties(propValue));
                        }
                    }
                }
            }
            catch (Exception err)
            {
                _somelog.WriteError($"Expection occurred trying to fix broken enum properties: {err}");
            }
            return list;
        }

           private static T GetDefaultEnumValue<T>(T entity, Type propertyType)
           {
               foreach (var enumValue in propertyType.GetEnumValues())
               {
                   if (String.Compare(enumValue.ToString(), "None", StringComparison.OrdinalIgnoreCase) == 0)
                   {
                       return (T)enumValue;
                   }
               }
               return entity;
           }

        private static bool IsEnumDefined(object entity, Type propertyType)
        {
            var castedValue = Convert.ChangeType(entity, propertyType);
            return Enum.IsDefined(propertyType, castedValue);
        }


With this guard, we can avoid that the entity does not load in case an illeagal value was loaded for a given enum. Note that our fallback is looking for the enum value mapping to the [None] enum member, so we fallback to the [None] enum value, if it exists. Mosts enum should have a [None] member mapping to the enum integer value 0. You can of course adjust the strategy used here. I believe such a consistency guard would be helpful for many applications using EF.

Thursday 2 May 2019

Regenerating precompiled views in Entity Framework

This article will present a solution to regenerate precompiled views in Entity Framework. Precompiled views can have a dramatic effect on the startup time of your DbContext / ObjectContext, especially the time to execute the first query against the database. First off, the following class can generate these precompiled views:

using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;

namespace PrecompiledViewGenerator
{
    /// <summary>
    /// Capable of generating pre compiled views that EF can use for quicker startup time when application domains starts.
    /// </summary>
    /// <typeparam name="TDbContext"></typeparam>
    /// <param name="dbContext"></param>
    /// <remarks>See https://github.com/ErikEJ/EntityFramework6PowerTools/tree/community/src/PowerTools Github page for the source code of EF Power tools.</remarks>
    /// <returns>A string containing the precompiled views that can be written to file or database for later use to gain optimized startup speeds of EF in application domains.</returns>
    public class EntityFrameworkPrecompiledViewGenerator
    {
        /// <summary>
        /// Generates pre compiled views from a db context. Uses EF Powertools runtime T4 template (.tt file) for precompiled view generation of views for EF 6 ObjectContext for C#.
        /// </summary>
        /// <typeparam name="TDbContext"></typeparam>
        /// <param name="dbContext"></param>
        /// <param name="viewContainerSuffix">The suffix to apply in the generated file containing the precompiled views</param>
        /// <remarks>See https://github.com/ErikEJ/EntityFramework6PowerTools/tree/community/src/PowerTools Github page for the source code of EF Power tools.</remarks>
        /// <returns>A string containing the precompiled views that can be written to file or database for later use to gain optimized startup speeds of EF in application domains.</returns>
        public string GeneratePrecompiledViews<TDbContext>(TDbContext dbContext, string viewContainerSuffix) where TDbContext : IObjectContextAdapter
        {
            if (string.IsNullOrEmpty(viewContainerSuffix))
                throw new ArgumentNullException(nameof(viewContainerSuffix));
            var objectContext = (dbContext as IObjectContextAdapter)?.ObjectContext; 
            if (objectContext == null)
                throw new ArgumentNullException(nameof(dbContext));
            var viewGenerator = new CSharpViewGenerator();
            var mappingCollection = (StorageMappingItemCollection) objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
            if (mappingCollection == null)
                throw new ArgumentNullException(nameof(dbContext));
            var listOfEdmSchemaErrors = new List<EdmSchemaError>();
            var views = mappingCollection.GenerateViews(listOfEdmSchemaErrors);
            listOfEdmSchemaErrors.ForEach(error =>
            {
                if (error.Severity == EdmSchemaErrorSeverity.Error)
                    throw new ArgumentOutOfRangeException($"An error occurred while trying to generate views for {dbContext.GetType().Name}. The error was: {error.ToString()}");
            });
            viewGenerator.ContextTypeName = dbContext.GetType().FullName;
            viewGenerator.MappingHashValue = mappingCollection.ComputeMappingHashValue();
            viewGenerator.ViewContainerSuffix = viewContainerSuffix;
            viewGenerator.Views = views;
            string precompiledViews = viewGenerator.TransformText();
            return precompiledViews;
        }
    }
}



The following runtime text template (.T4) is used to generate the precompiled views:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Data.Entity.Infrastructure.MappingViews;

[assembly: DbMappingViewCacheTypeAttribute(
    typeof(<#= ContextTypeName #>),
    typeof(Edm_EntityMappingGeneratedViews.ViewsForBaseEntitySets<#= ContextTypeName #>))]

namespace Edm_EntityMappingGeneratedViews
{
    using System;
    using System.CodeDom.Compiler;
    using System.Data.Entity.Core.Metadata.Edm;

    /// <summary>
    /// Implements a mapping view cache.
    /// </summary>
    [GeneratedCode("Entity Framework 6 Power Tools", "0.9.2.0")]
    internal sealed class ViewsForBaseEntitySets<#= ViewContainerSuffix #> : DbMappingViewCache
    {
        /// <summary>
        /// Gets a hash value computed over the mapping closure.
        /// </summary>
        public override string MappingHashValue
        {
            get { return "<#= MappingHashValue #>"; }
        }

        /// <summary>
        /// Gets a view corresponding to the specified extent.
        /// </summary>
        /// <param name="extent">The extent.</param>
        /// <returns>The mapping view, or null if the extent is not associated with a mapping view.</returns>
        public override DbMappingView GetView(EntitySetBase extent)
        {
            if (extent == null)
            {
                throw new ArgumentNullException("extent");
            }

            var extentName = extent.EntityContainer.Name + "." + extent.Name;
<#
    var index = 0;
    foreach (var view in Views)
    {
#>

            if (extentName == "<#= view.Key.EntityContainer.Name + "." + view.Key.Name #>")
            {
                return GetView<#= index #>();
            }
<#
        index++;
    }
#>

            return null;
        }
<#
    index = 0;
    foreach (var view in Views)
    {
#>

        /// <summary>
        /// Gets the view for <#= view.Key.EntityContainer.Name + "." + view.Key.Name #>.
        /// </summary>
        /// <returns>The mapping view.</returns>
        private static DbMappingView GetView<#= index #>()
        {
            return new DbMappingView(@"<#= view.Value.EntitySql #>");
        }
<#
        index++;
    }
#>
    }
}
<#+
    public string ContextTypeName { get; set; }
 public string ViewContainerSuffix { get; set; }
    public string MappingHashValue { get; set; }
    public dynamic Views { get; set; }
#>

This T4 file is compiled into the class CSharpViewGenerator. Our DbContext can now check the mapping hash value of the loaded precompiled views file in your assembly and compute in again to quickly assert if the database is in sync with the precompiled views. The following code can establish both a check that the precompiled views are in sync and run code that will regenerate the precompiled views file of which the developer can then copy from Notepad and into the precompiled view file again. Not perhaps an elegant solution, but it lets the developer easily check and keep the precompiled views file updated and in sync. And you do not need to install the EF Powertools extension either, as I use the .tt file and much of the source code from there which is part of the "Generate views" command anywyays! Sample DbContext is then:
using System;
using System.Data.Entity;
using System.Data.Entity.Core;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using Edm_EntityMappingGeneratedViews;

using PrecompiledViewGenerator;

namespace SomeAcme.SomeRegistry.Data
{
    public class SomeDatabaseMigrationsFactory : DatabaseMigrationsFactory<SomeDatabase>
    {
    }

    public class SomeDatabase : SomeDatabaseBaseClass
    {
        public DbSet<SomeEntity> SomeEntity { get; set; }

        public SomeDatabase(ISomeDependency dep)
            : base(dep)
        {
            var someEntityPrecompiledViewsMapping = new ViewsForBaseEntitySetsSomeEntityDatabase();
            var mappingCollection = (StorageMappingItemCollection)ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
            string mappingHashValue =  mappingCollection.ComputeMappingHashValue();
            if (SomeEntityPrecompiledViewsMapping.MappingHashValue != mappingHashValue)
            {
                var precompiledViewGenerator = new EntityFrameworkPrecompiledViewGenerator();
                string precompiledViewsContents = precompiledViewGenerator.GeneratePrecompiledViews(this, this.GetType().Name);
                string viewFileForMainDb = "SomeEntityDatabase.Views.cs";
                string temporaryPrecompiledViewFile = Path.Combine(Path.GetTempPath(), viewFileForMainDb);
                try
                {
                    File.WriteAllText(temporaryPrecompiledViewFile, precompiledViewsContents);
                    Process.Start("c:\\windows\\notepad.exe", temporaryPrecompiledViewFile);
                }
                catch (Exception err)
                {
                    throw new Exception("An error occured while trying to regenerate precompiled views for EF since the database changed. Error is: " + err);
                }
                throw new EntityCommandCompilationException($"The precompiled views file is not in sync with the database any longer. Replace the file {viewFileForMainDb} with the generated new contents!");
            }
        }
    }
}

The overall execution of code is the following:
  • In the DbContext constructor - check that the computed mapping hash value matches to that of the of the CSSpace storagemapping collection that your precompiled views file contains (MappingHashValue)
  • If the hash values do not agree, it is necessary to regenerate the pre compiled views file again. The contents are generated and written to a temporary file.
  • Notepad or similar is launched telling the developer to replace the pre compiled views file contents with this new contents.
  • An EntityCommandCompilationException is thrown as this is the same type of exception that is thrown if the precompiled views file does not agree
  • Developer replaces the contents and rebuilds the solution
  • The next time the startup time of EF should be reduced significantly again and work, since our DbContext and precomplied views are in sync again
Below is a sample of an exception thrown when my DbContext was not in sync with the precompiled views file:


System.Data.Entity.Core.EntityCommandCompilationException

System.Data.Entity.Core.EntityCommandCompilationException
  HResult=0x8013193B
  Message=An error occurred while preparing the command definition. See the inner exception for details.
  Source=EntityFramework
  StackTrace:
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory)
   at System.Data.Entity.Core.EntityClient.Internal.EntityProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree, DbInterceptionContext interceptionContext)
   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree)
   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Boolean streaming, Span span, IEnumerable`1 compiledQueryParameters, AliasGenerator aliasGenerator)
   at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   atProgram.cs:line 164

Inner Exception 1:
MappingException: The current model no longer matches the model used to pre-generate the mapping views, as indicated by the ViewsForBaseEntitySetsabf8c33ac61e42fc601fe7446b41eaf48c7577efe6d6e17ccccc2b434793c28e.MappingHashValue property. Pre-generated mapping views must be either regenerated using the current model or removed if mapping views generated at runtime should be used instead. See http://go.microsoft.com/fwlink/?LinkId=318050 for more information on Entity Framework mapping views.

 

Saturday 23 February 2019

Serializing a data contract with xml declaration and indented formatting

This code will serialize your object graph and also do xml indentation and adding an xml declaration at the top, using DataContractSerializer.



public static string SerializeObjectIndented(T dataContract, bool omitXmlDeclaration = false) where T : class
{
 using (var output = new StringWriter())
 {
  using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented })
  {
   if (!omitXmlDeclaration)
    writer.WriteStartDocument();
   var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T));
   serializer.WriteObject(writer, dataContract);
   
   return output.GetStringBuilder().ToString();
  }
 }
}

To use it, just pass in your object and get an xml back!

Tuesday 21 August 2018

Creating a validation attribute for multiple enum values in C#

This article will present a validation attribute for multiple enum value in C#. In C#, generics is not supported in attributes. The following class therefore specifyes the type of enum and provides a list of invalid enum values as an example of such an attribute.


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ValidateEnums
{

    public sealed class InvalidEnumsAttribute : ValidationAttribute
    {

        private List<object> _invalidValues = new List<object>();



        public InvalidEnumsAttribute(Type enumType, params object[] enumValues)
        {
            foreach (var enumValue in enumValues)
            {
                var _invalidValueParsed = Enum.Parse(enumType, enumValue.ToString());
                _invalidValues.Add(_invalidValueParsed);
            }
        }

        public override bool IsValid(object value)
        {
            foreach (var invalidValue in _invalidValues)
            {
                if (Enum.Equals(invalidValue, value))
                    return false;
            }
            return true;
        }

    }

}

Let us make use of this attribute in a sample class.

 public class Snack
    {
        [InvalidEnums(typeof(IceCream), IceCream.None, IceCream.All )]
        public IceCream IceCream { get; set; }

    }

We can then test out this attribute easily in NUnit tests for example:

[TestFixture]
    public class TestEnumValidationThrowsExpected
    { 

        [Test]
        [ExpectedException(typeof(ValidationException))]
        [TestCase(IceCream.All)]
        [TestCase(IceCream.None)]
        public void InvalidEnumsAttributeTest_ThrowsExpected(IceCream iceCream)
        {
            var snack = new Snack { IceCream = iceCream };
            Validator.ValidateObject(snack, new ValidationContext(snack, null, null), true);
        }

        [Test]
        public void InvalidEnumsAttributeTest_Passes_Accepted()
        {
            var snack = new Snack { IceCream = IceCream.Vanilla };
            Validator.ValidateObject(snack, new ValidationContext(snack, null, null), true);
            Assert.IsTrue(true, "Test passed for valid ice cream!"); 
        }


Sunday 19 August 2018

ConfigurationManager for .Net Core

.Net Core is changing a lot of the underlying technology for .Net developers migrating to this development environment. System.Configuration.ConfigurationManager class is gone and web.config and app.config files, which are XML-based are primrily replaced with .json files, at least in Asp.NET Core 2 for example. Let's look at how we can implement a class to let you at least be able to read AppSettings in your applicationSettings.json file which can be later refined. This implementation is my first version.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System.IO;
using System.Linq;

namespace WebApplication1
{

    public static class ConfigurationManager
    {

        private static IConfiguration _configuration;

        private static string _basePath;

        private static string[] _configFileNames;

        public static void SetBasePath(IHostingEnvironment hostingEnvironment)
        {
            _basePath = hostingEnvironment.ContentRootPath;
            _configuration = null;

            //fix base path
            _configuration = GetConfigurationObject();
        }

        public static void SetApplicationConfigFiles(params string[] configFileNames)
        {
            _configFileNames = configFileNames;
        }

        public static IConfiguration AppSettings
        {
            get
            {
                if (_configuration != null)
                    return _configuration;

                _configuration = GetConfigurationObject();
                return _configuration;
            }
        }

        private static IConfiguration GetConfigurationObject()
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(_basePath ?? Directory.GetCurrentDirectory());
            if (_configFileNames != null && _configFileNames.Any())
            {
                foreach (var configFile in _configFileNames)
                {
                    builder.AddJsonFile(configFile, true, true);
                }
            }
            else
                builder.AddJsonFile("appsettings.json", false, true);
            return builder.Build(); 
              
        }
    }
}

We can then easily get app settings from our config file:

  string endPointUri = ConfigurationManager.AppSettings["EmployeeWSEndpointUri"];

Sample appsettings.json file:
  {
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "EmployeeWSEndpointUri": "https://someserver.somedomain.no/someproduct/somewcfservice.svc"

}

 
If you have nested config settings, you can refer to these using the syntax SomeAppSetting:SomeSubAppSetting, like "Logging:Debug:LogLevel:Default".

Wednesday 8 August 2018

Doubly Linked List in C#

I am reading the book "C#7 and .NET Core 2.0 High Performance" about data structures and came accross Doubly linked lists. This is an interesting data structure. We most often use arrays and lists in .NET in everyday use, but both are not as high performant as linked lists when it comes to inserting and removing items in their structure. Removing an item and inserting an item in a list is only quick, if we add to the end of the list or remove from the end of the list. Arrays have the same behavior, if you have a large data structure with many items, consider using a LinkedList instead. .NET already got a good implementation of linked lists in System.Collections.Generic with the LinkedListNode class, so this article just presents a class I wrote for fun on my own. If you want to see the source code of the .Net class, it is available here:
LinkedListNode implementation(Reference Source /.NET)
Now how fun is it to just use .NET's implementation, we want to learn something and do things ourselves as devoted coders? Therefore I present my own implementation! You can find the source code by cloning the following Git repo: Actually, the implementation is easy, the most cumbersome part is to be careful with the next and previous pointers. Just like the .NET implementation, this class supports generic and a payload of different types, in the demo I will use string as the payload of each node.

git clone https://toreaurstad@bitbucket.org/toreaurstad/doublylinkedlist.git


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// ReSharper disable ArrangeThisQualifier
// ReSharper disable RedundantNameQualifier

namespace DoublyLinkedList
{

    /// <summary>
    /// Node in a doubly linked list data structure with pointers to the previous and next item in the linked list, if any.
    /// Allows quick insertion and removal of values in even large data structures
    /// </summary>
    /// <typeparam name="T">The type of Data in each node of the doubly linked list</typeparam>
    public class LinkedListNode<T>
    {

        public LinkedListNode(T data)
        {
            _data = data;
            _prev = null; //Init previous reference to null
            _next = null; //Init next reference to null
        }


        public T Data
        {
            get { return _data; }
        }

        /// <summary>
        /// Attempts to find a value in the doubly linked list. Uses object.Equals for comparison. O(N) complexity.
        /// </summary>
        /// <param name="value">Value to find</param>
        /// <returns>The first node with the matching value, if any.</returns>
        public LinkedListNode<T> Find(T value)
        {
            if (object.Equals(Data, value))
                return this;
            if (this._next is null)
                return null;
            return Find(this._next, value);
        }

        /// <summary>
        /// Attempts to find a value in the doubly linked list by a matchen with a given predicate. Returns null if no node values matches. O(N) complexity 
        /// </summary>
        /// <param name="searchCondition"></param>
        /// <returns></returns>
        public LinkedListNode<T> Find(Predicate<LinkedListNode<T>> searchCondition)
        {
            if (searchCondition(this))
                return this;
            if (this._next != null)
                return this._next.Find(searchCondition);
            return null;
        }

        /// <summary>
        /// Searches for multiple values and returns the nodes found. The search returns the first match if any for every search value. O(N*N) complexity.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public LinkedListNode<T>[] FindMultiple(params T[] values)
        {
            if (values is null)
                throw new ArgumentNullException(nameof(values));
            if (!values.Any())
                throw new ArgumentException("Please provide a nonempty array of values!");
            var foundValues = new List<LinkedListNode<T>>();
            foreach (T value in values)
            {
                LinkedListNode<T> foundValue = Find(value);
                if (foundValue != null)
                    foundValues.Add(foundValue);
            }

            return foundValues.ToArray();
        }

        // ReSharper disable once UnusedMember.Local
        private LinkedListNode<T> Find(LinkedListNode<T> node, Predicate<T> searchCondition)
        {
            if (node is null)
                return null;
            if (searchCondition(node.Data))
                return node;
            if (node._next != null)
                return Find(node._next, searchCondition);
            return null;
        }

        private LinkedListNode<T> Find(LinkedListNode<T> node, T value)
        {
            if (node is null)
                return null;
            if (object.Equals(node.Data, value))
                return node;
            if (node._next != null)
                return Find(node._next, value);
            return null;
        }

        /// <summary>
        /// Inserts a node into the doubly linked list. Adjusts the prev and next pointers of the inserted node. O(1) complexity.
        /// </summary>
        /// <param name="node">The node to insert, node's prev and next pointers will be overwritted if already set.</param>
        /// <returns>The inserted node with updated prev and next pointers</returns>
        public LinkedListNode<T> Insert(LinkedListNode<T> node)
        {
            if (node is null)
                throw new ArgumentNullException(nameof(node));

            LinkedListNode<T> nextNode = this._next;
            node._prev = this;
            this._next = node;
            node._next = nextNode;
            if (nextNode != null)
                nextNode._prev = node;

            return node;
        }

        /// <summary>
        /// Inserts multiple nodes into the doubly linked list by building nodes with passed in values. O(1) complexity.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public LinkedListNode<T>[] Insert(params T[] values)
        {
            if (values is null)
                throw new ArgumentNullException(nameof(values));
            if (!values.Any())
                throw new ArgumentException("Please provide a nonempty array of values!");

            values = values.Reverse().ToArray(); //Reverse order so insertion behaves sequentially 

            var inserted = new List<LinkedListNode<T>>();

            foreach (T value in values)
            {
                LinkedListNode<T> node = new LinkedListNode<T>(value);
                inserted.Add(Insert(node));
            }

            return inserted.ToArray();
        }

        /// <summary>
        /// Removes a node from the linked list. Adjusts the previous and next pointers of removed node. O(1) complexity.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public LinkedListNode<T> Remove(LinkedListNode<T> node)
        {
            if (node is null)
                throw new ArgumentNullException(nameof(node)); 

            if (node._prev != null)
                node._prev._next = node._next;
            if (node._next != null)
                node._next._prev = node._prev;

            //Set unneeded references to null now and to avoid misuse
            node._prev = null;
            node._next = null;

            return node;
        }

        public void Remove()
        {
            if (this._prev != null)
                this._prev._next = this._next;
            if (this._next != null)
                this._next._prev = this._prev;

            //Set unneeded references to null now and to avoid misuse
            this._prev = null;
            this._next = null;
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (this._prev is null)
                sb.Append(Head);
            sb.Append(_data + GetArrow(this));
            IterateLinkedList(this._next, sb);
            return sb.ToString();
        }

        /// <summary>
        /// Iterates the doubly linked list and builds a string to output in the ToString() method
        /// </summary>
        /// <param name="node">LinkedListNode</param>
        /// <param name="sb">StringBuilder</param>
        private void IterateLinkedList(LinkedListNode<T> node, StringBuilder sb)
        {
            if (node != null)
            {
                sb.Append(node.Data + GetArrow(node));
                if (node._next != null)
                    IterateLinkedList(node._next, sb);
            }
        }

        private string GetArrow(LinkedListNode<T> node)
        {
            if (node != null)
            {
                if (node._next != null && node._next._prev != null)
                    return DoubleArrow;
                if (node._next != null && node._next._prev == null)
                    return Arrow;
                if (node._next == null)
                    return Arrow + NullString;
            }

            return ArrowUndefined;
        }

        private const string Head = "HEAD->";

        private const string Arrow = "->";

        private const string DoubleArrow = "<->";

        private const string ArrowUndefined = "??MISSINGLINK??";

        private const string NullString = "NULL";

        private readonly T _data;

        private LinkedListNode<T> _prev;

        private LinkedListNode<T> _next;

    }
}


This implementation has not got a specific pointer to the head of the list like a circular linked list can provide. The following code makes use of this class to demonstrate its usage:

using System;
using System.Diagnostics;
using System.Linq;

namespace DoublyLinkedList
{
    class Program
    {
        // ReSharper disable once UnusedParameter.Local
        static void Main(string[] args)
        {
            var root = new LinkedListNode("Hello");
            root.Insert(new LinkedListNode("world"));
            root.Insert(new LinkedListNode("Testing"));
            root.Insert(new LinkedListNode("Double linked list!"));

            root.Insert("Inserting", "some", "values!");

            root.Insert("Delete", "me", "please");

            root.FindMultiple("Delete", "me").ToList().ForEach(n => n.Remove(n));

            root.Find(n => n.Data.Contains("pl")).Remove();

            var mismatch = root.Find("Nonexisting value");
            Debug.Assert(mismatch is null, "Expected to not find any item in this doubly linked list with this search value");

            string rootRepresentation = root.ToString();

            Debug.Assert(rootRepresentation == @"HEAD->Hello<->Inserting<->some<->values!<->Double linked list!<->Testing<->world->NULL");

            Console.WriteLine(rootRepresentation);

            Console.ReadKey();
        }
    }
}

The output of this linked list is displaying the contents of the doubly linked list:

HEAD->Hello<->Inserting<->some<->values!<->Double linked list!<->Testing<->world->NULL

As we can see, with our ToString implementation we can deduce that the first and last node is special, the first one lacks a prev pointer illustrated by "HEAD->" and the last node lacks a next pointer illustrated with "->NULL". You will find this in the implementation of the class. I have decided to actually revert the order if the client wants to insert multiple values, as that ordering behaves more naturally. The client can look after a value or multiple values or search with a given predicate, or pass in a node and use it to search. Also, it is possible to remove a node. We end up with an implementation of a Doubly Linked list that can be used in many scenarios. I would advice you to use the .NET version as it supports more features, such as a pointer to the HEAD node. But this implementation is compact and easy to understand for many developers. You will usually use linked list in scenarios where you have much data and want to quickly insert or remove one or several nodes in the linked list. It also supports quick navigation from a node to its previous or next node. Imagine for example working with a class called Book which needs to have an iterable structure ("Pages") to move to the next and previous page and at the same time insert new pages or removing a page from the middle of the data structure. Using an array or a list would be low performant and slow, while a doubly linked list would actually allow the developer to create code that quickly inserts a new page or removes a page at an arbitrary position in the data structure of the Book. This class can of course be optimized to support for example circular linked list with a pointer always to HEAD, or maybe you want to have pointer to HEAD and TAIL and not have a circular list? The source code should be relatively self explanatory for the intermediate C#-developer to revise and improve. I hope you found this article interesting.

Tuesday 7 August 2018

Swapping variables in C# Unmanaged / Managed

This article will shortly present two ways of swapping variables in C#. Specifically, these two ways are only both available for value types and structs and unmanaged types, while the managed swap by using ref is available for values, structs and managed structs. The method UnsafeSwap swaps two variables by using unsafe code and pointers. By passing in the address of the two variables to swap, it is possible to use the dereference operator * to not only copy into a temporary variable but also use the syntax *a = *b to exchange the address the variable is pointing to, effectively we swap to variables with their content, here int is used. Another way is do a SafeSwap where we pass in the ref of the variables and just change their contents. Note that if you want to exchange two strings, you must pin the pointer of the chars using the fixed keyword.

unsafe void Main()
{
 int one = 20;
 int two = 30;

 Console.WriteLine("Before swap, one: {0}, two: {1}", one, two);

 UnsafeSwap(&one, &two);
 
 Console.WriteLine("Unsafe swap, one: {0}, two: {1}", one, two); 
 
 SafeSwap(ref one, ref two);

 Console.WriteLine("Safe swap back again, one: {0}, two: {1}", one, two);

}

unsafe void UnsafeSwap(int* a, int* b){
 int temp = *a;
 *a = *b;
 *b = temp; 
}

void SafeSwap(ref int a, ref int b){
 int temp = a;
 a = b;
 b = temp;
}


To exchange two string variables, we must use the fixed keyword and of course only be able to exchange the characters from the char array consisting the first variable to be exchanged with the char array of the second variable. In addition, the string in C# is at a low level actually a character array null terminated with the '\0' sequence, at least when a string is treated as a character array.. The following method will exchange two string variables using unsafe / unmanaged code. Note that the two strings differ in length, so the last character is not exchanged. That is - our string is actually a character array and consists of multiple memory addresses.
unsafe void Main()
{
 fixed (char* one = "hello??")
 {
  fixed (char* two = "world!")
  {
   char* ptrone = one;
   char* ptrtwo = two;

   while (*ptrone != '\0' && *ptrtwo != '\0')
   {
    Swap(ptrone, ptrtwo);
    Console.WriteLine("one: {0}", GetString(one));
    Console.WriteLine("two: {0}", GetString(two));
    ++ptrone;
    ++ptrtwo;
   }

  }
 }
 
}

unsafe void Swap(char* first, char* second){
 char temp = *first;
 *first = *second;
 *second = temp;
}

unsafe string GetString(char* input){
 char* ptr = input; 
 var sw = new StringBuilder();
 while (*ptr != '\0')
 {
  sw.Append(ptr->ToString());
  ++ptr;
 }
 return sw.ToString();
}

The output in Linqpad gives as the exchange of the string or actually a null terminated character array progresses:

one: wello?? two: horld! one: wollo?? two: herld! one: worlo?? two: helld! one: worlo?? two: helld! one: world?? two: hello! one: world!? two: hello?

Monday 6 August 2018

Simple Base64 encoder in C#

Just read a bit about Base64 encoding and decided to try out writing my own in Linqpad for strings! The way you Base64 encode is to treat each char in the input string as a byte value with groups of six bytes (this byte value is zero padded left) and then mapping the 2^6 values into a Base64 table and outputting the corresponding values into a resulting string. Note that you also pad the Base64 string with '=' char to ensure the entire bit length is divisible with three. That is why Base64 strings in .NET always have 0,1 or 2 '=' chars at the end. The characters used in the Base64 encoding is in .NET the chars [A-z] and [0-9] plus + and slash /.

void Main()
{
 string wordToBase64Encode = "Hello world from base64 encoder. This is a sample input string, does it work?"; 
 string wordBase64EncodedAccordingToNet = Convert.ToBase64String(Encoding.ASCII.GetBytes(wordToBase64Encode)).Dump();
 string wordBase64EncodedAccordingToCustomBase64 = wordToBase64Encode.ToBase64String().Dump();
 (("Are the two strings equal?: ") + string.Equals(wordBase64EncodedAccordingToNet, wordBase64EncodedAccordingToCustomBase64)).Dump();
 
}

public static class LowLevelBase64Extensions {

    private static readonly char[] _base64Table =
 {
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 
  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 
  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
 };

 public static string ToBase64String(this string toBeEncoded){
     byte[] toBeEncodedByteArray = Encoding.ASCII.GetBytes(toBeEncoded);
  string toBeEncodedBinaryString = 
  string.Join("", 
   toBeEncodedByteArray.Select(b => (Convert.ToString(b, 2).PadLeft(8, '0'))));
   
  //toBeEncodedBinaryString.Length.Dump();
   
  int padCharacters = toBeEncodedBinaryString.Length % 3;
  //toBeEncoded.Dump();
       
  StringWriter sw = new StringWriter();

  for (var i = 0; i < toBeEncodedBinaryString.Length; i = i + 6)
  {
   string encodingToMap =
    toBeEncodedBinaryString.Substring(i, Math.Min(toBeEncodedBinaryString.Length - i, 6))
    .PadRight(6, '0');
   //encodingToMap.Dump();
   byte encodingToMapByte = Convert.ToByte(encodingToMap, 2);
   char encodingMapped = _base64Table[(int)encodingToMapByte];
   sw.Write(encodingMapped);
  }
  
  sw.Write(new String('=', padCharacters));
  
  //Check 24 bits / 3 byte padding 
  return sw.ToString();
 }
}

Note - the casting to int of the encodingToMapByte also works if you cast the byte representation to short or byte. I have compared this custom Base64Encoder with .NET's own Convert.ToBase64String(), and they give equal strings in the use cases I have tried out. Make note that this is just playing around, .NET's own method is optimized for speed. This is more to show what happens with the input string to generate a Base64 encoded string. You can use this code as a basis for custom encoding shemes like Base32. I have used Encoding.ASCII.GetBytes to look up the ASCII code. So this implementation primarily supports input strings in languages using ASCII and Extended ASCII characters, at least that is what I have tested it with. The output in Linqpad shows the following corresponding results:

Wednesday 1 August 2018

Controlling WCF serialization and deserialization with IXmlSerializable

It is possible to customize how WCF serializes and deserializes objects to be sent over the wire. The default way to serialize and deserialize objects with WCF is using DataContractSerializer. There are many scenarios where you instead want to control this more in your WCF services. For interoperability scenarios with other platforms or perhaps you want to change the way WCF serializes objects. Perhaps using attributes more than child elements, so the XML can be condensed more. Either way, you can end up in situations where you must handle the serialization and deserialization in WCF in more detail, then IXmlSerializable is one option. Read on for a simple demo. Another, more fine-grained way of actually customizing the way WCF serializes objects and deserialize them is using IXmlSerializable interface. I have added a solution on Bitbucket, which allows you to see how this is done here:

git clone https://toreaurstad@bitbucket.org/toreaurstad/wcfixmlserializabledemo.git The source code is here: WcfIXmlSerializableDemo
The core of the serialization is done implementing the interface IXmlSerializable. The following class serves as a demonstration:
 using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace CustomWcfSerialization.Common
{
  
    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [XmlRoot("Animal", Namespace ="http://schemas.toreaurstad.no/2018/08")]
    public class Animal : IXmlSerializable
    {
       
        public Animal()
        {

        }

        bool _isBipedal;
        public bool IsBipedal
        {
            get { return _isBipedal; }
            set { _isBipedal = value; }
        }

        string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();
   
            Name = reader.GetAttribute("Name");
            reader.ReadStartElement(); 

            IsBipedal = bool.Parse(reader.ReadElementString("IsBipedal") == "Yes" ? "true" : "false");
            reader.ReadEndElement(); 
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString("Name", Name);
            writer.WriteElementString("IsBipedal", IsBipedal ? "Yes" : "No");
        }

    }
}

The serialized request and response from WCF now is changed from the default serialization of DataContractSerializer, to not only support XML attributes - but also represent booleans as a custom boolean where true and false is exchanged with "Yes" and "No".

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>

<GetAnimalsResponse xmlns="http://tempuri.org/">
<GetAnimalsResult xmlns:a="http://schemas.datacontract.org/2004/07/CustomWcfSerialization.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Animal Name="Rex"><IsBipedal>No</IsBipedal></a:Animal>
<a:Animal Name="Bubbles"><IsBipedal>Yes</IsBipedal>
</a:Animal>
</GetAnimalsResult> </GetAnimalsResponse></s:Body></s:Envelope>

Note though, that even we used special values for boolean values in our sample ("Yes" and "No"), it was possible to deserialize this by implementing the deserialization in the ReadXml method of our WCF service entity class Animal. This image shows that Visual Studio is able to deserialize the data into objects properly even that the XML presents data that is not directly compatible by .NET:




This is done by manually parsing the data retrieved from WCF like this:

IsBipedal = bool.Parse(reader.ReadElementString("IsBipedal") == "Yes" ? "true" : "false");

You can quickly end up with much code if there is much code you want to serialize in a specific manner. It is possible use .NET reflection, generics and the [KnownType] argument for this in case you want to support this is a more generic manner. I will look into this in a future article.