Skip to content
Permalink
Browse files

fix(#540): Mapper register method throw ArgumentException (#541)

* fix(#540): Mapper register method throw ArgumentException

#Issue
link #540

* fix: GetMapper check both type and assembly in the key
  • Loading branch information...
ArgoZhang authored and pleb committed Aug 1, 2019
1 parent 070f3f3 commit aa73080afa981a1c06ee981a20f99d89d8c6bfea
Showing with 67 additions and 78 deletions.
  1. +35 −0 PetaPoco.Tests.Unit/Core/MapperTest.cs
  2. +32 −78 PetaPoco/Core/Mappers.cs
@@ -0,0 +1,35 @@
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace PetaPoco.Tests.Unit.Core
{
public class MapperTest
{
private class StringMapperTest : ConventionMapper
{
public StringMapperTest()
{
Thread.Sleep(2000);
}
}

[Fact]
public void Register_Ok()
{
NoThrowExceptionMethod();
}

private void NoThrowExceptionMethod()
{
var t1 = Task.Run(() => RegisterMethod());
var t2 = Task.Run(() => RegisterMethod());
Task.WaitAll(t1, t2);
}

private void RegisterMethod()
{
if (Mappers.GetMapper(typeof(string), null) == null) Mappers.Register(typeof(string), new StringMapperTest());
}
}
}
@@ -1,10 +1,10 @@
using System;
using PetaPoco.Core;
using PetaPoco.Internal;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using PetaPoco.Core;
using PetaPoco.Internal;

namespace PetaPoco
{
@@ -13,81 +13,58 @@ namespace PetaPoco
/// </summary>
public static class Mappers
{
private static Dictionary<object, IMapper> _mappers = new Dictionary<object, IMapper>();
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static ConcurrentDictionary<object, Lazy<IMapper>> _mappers = new ConcurrentDictionary<object, Lazy<IMapper>>();

/// <summary>
/// Registers a mapper for all types in a specific assembly
/// </summary>
/// <param name="assembly">The assembly whose types are to be managed by this mapper</param>
/// <param name="mapper">The IMapper implementation</param>
public static void Register(Assembly assembly, IMapper mapper)
{
RegisterInternal(assembly, mapper);
}
public static bool Register(Assembly assembly, IMapper mapper) => RegisterInternal(assembly, mapper);

/// <summary>
/// Registers a mapper for a single POCO type
/// </summary>
/// <param name="type">The type to be managed by this mapper</param>
/// <param name="mapper">The IMapper implementation</param>
public static void Register(Type type, IMapper mapper)
{
RegisterInternal(type, mapper);
}
public static bool Register(Type type, IMapper mapper) => RegisterInternal(type, mapper);

/// <summary>
/// Remove all mappers for all types in a specific assembly
/// </summary>
/// <param name="assembly">The assembly whose mappers are to be revoked</param>
public static void Revoke(Assembly assembly)
{
RevokeInternal(assembly);
}
public static bool Revoke(Assembly assembly) => RevokeInternal(assembly);

/// <summary>
/// Remove the mapper for a specific type
/// </summary>
/// <param name="type">The type whose mapper is to be removed</param>
public static void Revoke(Type type)
{
RevokeInternal(type);
}
public static bool Revoke(Type type) => RevokeInternal(type);

/// <summary>
/// Revoke an instance of a mapper
/// </summary>
/// <param name="mapper">The IMapper to be revkoed</param>
public static void Revoke(IMapper mapper)
public static bool Revoke(IMapper mapper)
{
_lock.EnterWriteLock();
try
var ret = false;
var m = _mappers.FirstOrDefault(v => v.Value.Value == mapper);
var key = m.Equals(default(KeyValuePair<object, Lazy<IMapper>>)) ? null : m.Key;
if (key != null)
{
foreach (var i in _mappers.Where(kvp => kvp.Value == mapper).ToList())
_mappers.Remove(i.Key);
}
finally
{
_lock.ExitWriteLock();
FlushCaches();
ret = _mappers.TryRemove(key, out var _);
if (ret) FlushCaches();
}
return ret;
}

/// <summary>
/// Revokes all registered mappers.
/// </summary>
public static void RevokeAll()
{
_lock.EnterWriteLock();
try
{
_mappers.Clear();
}
finally
{
_lock.ExitWriteLock();
FlushCaches();
}
_mappers.Clear();
FlushCaches();
}

/// <summary>
@@ -98,49 +75,26 @@ public static void RevokeAll()
/// <returns>The mapper for the given type.</returns>
public static IMapper GetMapper(Type entityType, IMapper defaultMapper)
{
_lock.EnterReadLock();
try
{
IMapper val;
if (_mappers.TryGetValue(entityType, out val))
return val;
if (_mappers.TryGetValue(entityType.Assembly, out val))
return val;
if (_mappers.TryGetValue(entityType, out Lazy<IMapper> val))
return val.Value;
if (_mappers.TryGetValue(entityType.Assembly, out val))
return val.Value;

return defaultMapper;
}
finally
{
_lock.ExitReadLock();
}
return defaultMapper;
}

private static void RegisterInternal(object typeOrAssembly, IMapper mapper)
private static bool RegisterInternal(object typeOrAssembly, IMapper mapper)
{
_lock.EnterWriteLock();
try
{
_mappers.Add(typeOrAssembly, mapper);
}
finally
{
_lock.ExitWriteLock();
FlushCaches();
}
var ret = _mappers.TryAdd(typeOrAssembly, new Lazy<IMapper>(() => mapper));
if (ret) FlushCaches();
return ret;
}

private static void RevokeInternal(object typeOrAssembly)
private static bool RevokeInternal(object typeOrAssembly)
{
_lock.EnterWriteLock();
try
{
_mappers.Remove(typeOrAssembly);
}
finally
{
_lock.ExitWriteLock();
FlushCaches();
}
var ret = _mappers.TryRemove(typeOrAssembly, out var _);
if (ret) FlushCaches();
return ret;
}

private static void FlushCaches()

0 comments on commit aa73080

Please sign in to comment.
You can’t perform that action at this time.