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

Version 1.0.9 - Equipment

  • New equipment beta feature, you can now buy armor and weapons in the store.
  • New active attribute booster items
  • Optimizations 

View on blog

Last updated: 2021-10-12 22:49

Version 1.0.8

 

  • Added 5 more avatars 
  • Various bugfixes.

View on blog

Last updated: 2021-10-12 22:48

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

Version 1.0.7 - Location and My Statistics

  • The location will have an elemental affinity by most monster. 
  • Various bugfixes.
  • Added my statistics page.
  • Balanced battle.

View on blog

Last updated: 2021-09-12 22:37

Version 1.0.6 - Monster Battles

  • Added SVG monster on fought monsters
  • Added SVG monster on battle result dialog
  • Fixed issue where one extra round is triggered after the victim is fallen.

View on blog

Last updated: 2021-09-12 22:37

Welcome

Hello, 

Welcome to our blog Pixel Encounter. Our API can be used for free to generate SVG monsters.

We will use this blog to post news about new releases of the Pixel Encounter API and the game. This is our first post on blogger and it will be used as a feed on our homepage.

View on blog

Last updated: 2021-08-27 16:53

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