-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
o.nadymov
committed
Jun 17, 2024
1 parent
54b09a8
commit d1f0874
Showing
6 changed files
with
257 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Spoleto.Common.Tests.Objects | ||
{ | ||
public class TestTypeClass | ||
{ | ||
public Type MyType { get; set; } | ||
|
||
public Type SystemType { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace Spoleto.Common.Helpers | ||
{ | ||
/// <summary> | ||
/// The helper for serialization of types. | ||
/// </summary> | ||
public static class SerializedTypeHelper | ||
{ | ||
/// <summary> | ||
/// Custom binder type. | ||
/// </summary> | ||
public static Func<string, Type> BindToType { get; set; } = DefaultBindToType; | ||
|
||
/// <summary> | ||
/// Gets the type name does not have Version, Culture, Public token. | ||
/// </summary> | ||
public static bool RemoveAssemblyVersion = true; | ||
|
||
private static readonly Regex SubtractFullNameRegex = new Regex(@", Version=\d+.\d+.\d+.\d+, Culture=\w+, PublicKeyToken=\w+", RegexOptions.Compiled); | ||
|
||
// mscorlib or System.Private.CoreLib | ||
private static readonly bool IsMscorlib = typeof(int).AssemblyQualifiedName.Contains("mscorlib"); | ||
|
||
private static readonly Dictionary<string, Type> TypeCache = []; | ||
Check failure on line 28 in src/Spoleto.Common/Helpers/SerializedTypeHelper.cs GitHub Actions / Build-Tests-Publish
Check failure on line 28 in src/Spoleto.Common/Helpers/SerializedTypeHelper.cs GitHub Actions / Build-Tests-Publish
Check failure on line 28 in src/Spoleto.Common/Helpers/SerializedTypeHelper.cs GitHub Actions / Build-Tests-Publish
|
||
|
||
/// <summary> | ||
/// Deserializes the type. | ||
/// </summary> | ||
/// <param name="typeName"></param> | ||
/// <returns></returns> | ||
public static Type DeserializeType(string typeName) | ||
{ | ||
lock (((ICollection)TypeCache).SyncRoot) | ||
{ | ||
if (!TypeCache.TryGetValue(typeName, out var type)) | ||
{ | ||
type = BindToType(typeName); | ||
if (type == null) | ||
{ | ||
if (IsMscorlib && typeName.Contains("System.Private.CoreLib")) | ||
{ | ||
typeName = typeName.Replace("System.Private.CoreLib", "mscorlib"); | ||
type = Type.GetType(typeName); | ||
} | ||
else if (!IsMscorlib && typeName.Contains("mscorlib")) | ||
{ | ||
typeName = typeName.Replace("mscorlib", "System.Private.CoreLib"); | ||
type = Type.GetType(typeName); | ||
} | ||
else | ||
{ | ||
type = Type.GetType(typeName); | ||
} | ||
} | ||
|
||
if (type == null) | ||
{ | ||
throw new TypeLoadException($"Cannot load type by the name <{typeName}>."); | ||
} | ||
|
||
TypeCache[typeName] = type; | ||
} | ||
|
||
return type; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Builds the type name for serialization. | ||
/// </summary> | ||
/// <param name="type"></param> | ||
/// <returns></returns> | ||
public static string BuildTypeName(Type type) | ||
{ | ||
if (RemoveAssemblyVersion) | ||
{ | ||
string full = type.AssemblyQualifiedName; | ||
|
||
var shortened = SubtractFullNameRegex.Replace(full, String.Empty); | ||
if (Type.GetType(shortened) == null) | ||
{ | ||
// if type cannot be found with shortened name - use full name | ||
shortened = full; | ||
} | ||
|
||
return shortened; | ||
} | ||
else | ||
{ | ||
return type.AssemblyQualifiedName; | ||
} | ||
} | ||
|
||
private static Type DefaultBindToType(string typeName) => Type.GetType(typeName); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Spoleto.Common.Helpers; | ||
|
||
namespace Spoleto.Common.JsonConverters | ||
{ | ||
/// <summary> | ||
/// The custom Json converter for the <see cref="Type"/>. | ||
/// </summary> | ||
public class JsonTypeConverter : JsonConverter<Type> | ||
{ | ||
/// <summary> | ||
/// The default constructor to initialize a Json converter for the <see cref="Type"/>. | ||
/// </summary> | ||
public JsonTypeConverter() | ||
{ | ||
} | ||
|
||
public override Type Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
if (reader.TokenType == JsonTokenType.Null) | ||
return null; | ||
|
||
var typeName = reader.GetString(); | ||
|
||
if (typeName == null) | ||
return null; | ||
|
||
var resolvedType = SerializedTypeHelper.DeserializeType(typeName); | ||
|
||
if (resolvedType == null) | ||
{ | ||
throw new JsonException($"Unable to resolve type {typeName}"); | ||
} | ||
|
||
return resolvedType; | ||
} | ||
|
||
public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) | ||
{ | ||
if (value == null) | ||
{ | ||
writer.WriteNullValue(); | ||
return; | ||
} | ||
|
||
// Write the assembly-qualified name | ||
var typeName = SerializedTypeHelper.BuildTypeName(value); | ||
writer.WriteStringValue(typeName); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
using System; | ||
using System.Runtime.Serialization; | ||
using Spoleto.Common.Helpers; | ||
|
||
namespace Spoleto.Common.Objects | ||
{ | ||
/// <summary> | ||
/// String representation of Type. | ||
/// </summary> | ||
[DataContract] | ||
[Serializable] | ||
public class WebType | ||
{ | ||
/// <summary> | ||
/// Default constructor. | ||
/// </summary> | ||
public WebType() | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Constructor with parameter. | ||
/// </summary> | ||
/// <param name="type"></param> | ||
public WebType(Type type) | ||
{ | ||
if (type != null) | ||
{ | ||
TypeName = SerializedTypeHelper.BuildTypeName(type); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Full type name with assembly name. | ||
/// </summary> | ||
[DataMember] | ||
public string TypeName { get; set; } | ||
|
||
/// <summary> | ||
/// Gets the real type. | ||
/// </summary> | ||
public Type GetRealType() => TypeName != null ? SerializedTypeHelper.DeserializeType(TypeName) : null; | ||
|
||
/// <summary> | ||
/// User-defined conversion from Type to WebType. | ||
/// </summary> | ||
/// <param name="type"></param> | ||
public static explicit operator WebType(Type type) | ||
{ | ||
return new WebType(type); | ||
} | ||
|
||
/// <summary> | ||
/// User-defined conversion from WebType to Type. | ||
/// </summary> | ||
/// <param name="webType"></param> | ||
public static explicit operator Type(WebType webType) | ||
{ | ||
return webType?.GetRealType(); | ||
} | ||
|
||
/// <summary> | ||
/// Returns the string representation. | ||
/// </summary> | ||
/// <returns></returns> | ||
public override String ToString() => TypeName; | ||
} | ||
} |