Posts

How deserialize TimeSpan in .NET 6 serialized with .NET 5?

Trouble deserialize TimeSpan from .NET 5 to .NET 6? 

This time we were migrating to .NET 6 and we had problem with serialized values from .NET 5 which where saved in our document database as a object. To fix this issue we made our custom converter.
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Tutorial.JsonConverters.PixelEncounter
{
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (TryParseOldTimespanObject(ref reader, out TimeSpan ts))
{
return ts;
}

return TimeSpan.Parse(reader.GetString());
}

public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}

private static bool TryParseOldTimespanObject(ref Utf8JsonReader reader, out TimeSpan ts)
{
ts = TimeSpan.Zero;
if (reader.TokenType == JsonTokenType.StartObject)
{
var ticksPropertyName = "";
var ticks = 0L;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}

if (reader.TokenType == JsonTokenType.PropertyName)
{
ticksPropertyName = reader.GetString();
continue;
}

SetTicksIfPropertyFound(ref reader, ticksPropertyName, ref ticks);
// Read until EndObject is required.
}

ts = new TimeSpan(ticks);
return true;
}

return false;
}

private static void SetTicksIfPropertyFound(ref Utf8JsonReader reader, string ticksPropertyName, ref long ticks)
{
if (ticksPropertyName == "Ticks" && reader.TokenType == JsonTokenType.Number)
{
ticks = reader.GetInt64();
}
}
}
}

View on blog

Last updated: 2021-11-11 11:43

How to unit test if all required dependencies have been registered

 Hi, 

I am currently implementing prism.js on pixelencounter.com for that I will use this post with some C# code to try it out. I have decided I will write some code on how to unit test required business logic dependencies so they are registered in the container.

The code below is an example, it will help me to not forget to register services.


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using FluentAssertions;
using Tutorial.BusinessLogic.Extensions;
using Tutorial.BusinessLogic.Interfaces.Battles;
using Tutorial.BusinessLogic.Stores;
using Tutorial.Core.Extensions;
using Tutorial.Core.Models.Identity;
using Tutorial.Infrastructure.BackgroundWorker;
using Tutorial.Infrastructure.Entity;
using Tutorial.Infrastructure.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.Internal;
using Xunit;
using BusinessLogicSharedResource = Tutorial.BusinessLogic.SharedResource;

namespace Tutorial.Tests.PixelEncounter
{
public class ServiceCollectionTest
{
internal class TestApplication
{
private readonly ApplicationDbContext _db;

public TestApplication(ApplicationDbContext db)
{
_db = db;
}

public bool CanInject()
{
return _db != null;
}
}

[Fact]
public void BuildServiceProviderInjectedDepedency()
{
IServiceCollection services = CreateServices();
services.AddSingleton<TestApplication>();
using var sut = services.BuildServiceProvider();
var application = sut.GetRequiredService<TestApplication>();
application.CanInject().Should().BeTrue();
}

[Fact]
public void GetServicesReturnAllBusinessLogicServices()
{
IServiceCollection services = CreateServices();
using var sut = services.BuildServiceProvider();

var serviceTypes = GetInterfaceTypesForBusinessLogicServices();
foreach (var serviceType in serviceTypes)
{
var service = sut.GetRequiredService(serviceType);
service.Should().NotBeNull();
}
}

private static IEnumerable<Type> GetInterfaceTypesForBusinessLogicServices()
{
var blackList = new Type[]
{
typeof(ITestAbstractService)
};

return GetInterfaceTypesForServices(typeof(BusinessLogicSharedResource), blackList);
}

private static IEnumerable<Type> GetInterfaceTypesForServices(Type assemblyType, params Type[] blacklist)
{
var ns = assemblyType.Namespace;
var query = from t in Assembly.GetAssembly(assemblyType).GetTypes()
where t.IsInterface && t.Namespace.StartsWith($"{ns}.Interfaces")
select t;

if (blacklist?.Length > 0)
{
query = query.Where(t => !blacklist.Any(b => b.Equals(t)));
}

return query;
}

private static IConfiguration SetupConfiguration()
{
return new ConfigurationBuilder()
.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appsettings.json", true)
.AddUserSecrets<Program>()
.Build();
}

private static IServiceCollection CreateServices()
{
var configuration = SetupConfiguration();

IServiceCollection services = new ServiceCollection();
services.AddSingleton(configuration);
services.AddLogging();
services.AddLocalization();

var env = new HostingEnvironment { EnvironmentName = Environments.Development };
services.AddSingleton<IHostEnvironment>(env);

services.AddDbContextPool<ApplicationDbContext>(option =>
{
option.UseInMemoryDatabase(nameof(ServiceCollectionTest));
});

services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();

services.AddOptions();
services.AddDistributedMemoryCache();
services.AddHostedService<QueuedHostedService>();

services.AddCore();
services.AddInfrastructure();
services.AddConfiguratedAutoMapperProfiles();
services.AddBusinessLogic();

return services;
}
}
}

View on blog

Last updated: 2021-09-13 11:22

The date after the article title is the published date. Each post may have tag links which can be used to filter the posts.