Isolated Content Serialization
- Added IContentSerializer, JsonContentSerializer, XmlContentSerializer - RefitSettings allows the IContentSerializer to be specified - Refit defaults to JsonContentSerializer for back-compat - Tests modified to exercise Json and Xml Serialization - .NET Standard 1.4 has package dep on System.Xml.XmlSerializer
This commit is contained in:
Родитель
dc69773a31
Коммит
27d6fb4865
|
@ -402,9 +402,16 @@ namespace Refit.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultipartUploadShouldWorkWithAnObject()
|
||||
[Theory]
|
||||
[InlineData(typeof(JsonContentSerializer), "application/json")]
|
||||
[InlineData(typeof(XmlContentSerializer), "application/xml")]
|
||||
public async Task MultipartUploadShouldWorkWithAnObject(Type contentSerializerType, string mediaType)
|
||||
{
|
||||
if (!(Activator.CreateInstance(contentSerializerType) is IContentSerializer serializer))
|
||||
{
|
||||
throw new ArithmeticException($"{contentSerializerType.FullName} does not implement {nameof(IContentSerializer)}");
|
||||
}
|
||||
|
||||
var model1 = new ModelObject
|
||||
{
|
||||
Property1 = "M1.prop1",
|
||||
|
@ -421,8 +428,8 @@ namespace Refit.Tests
|
|||
|
||||
Assert.Equal("theObject", parts[0].Headers.ContentDisposition.Name);
|
||||
Assert.Null(parts[0].Headers.ContentDisposition.FileName);
|
||||
Assert.Equal("application/json", parts[0].Headers.ContentType.MediaType);
|
||||
var result0 = JsonConvert.DeserializeObject<ModelObject>(await parts[0].ReadAsStringAsync());
|
||||
Assert.Equal(mediaType, parts[0].Headers.ContentType.MediaType);
|
||||
var result0 = serializer.Deserialize<ModelObject>(await parts[0].ReadAsStringAsync());
|
||||
Assert.Equal(model1.Property1, result0.Property1);
|
||||
Assert.Equal(model1.Property2, result0.Property2);
|
||||
}
|
||||
|
@ -430,16 +437,24 @@ namespace Refit.Tests
|
|||
|
||||
var settings = new RefitSettings()
|
||||
{
|
||||
HttpMessageHandlerFactory = () => handler
|
||||
HttpMessageHandlerFactory = () => handler,
|
||||
ContentSerializer = serializer
|
||||
};
|
||||
|
||||
var fixture = RestService.For<IRunscopeApi>(BaseAddress, settings);
|
||||
var result = await fixture.UploadJsonObject(model1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultipartUploadShouldWorkWithObjects()
|
||||
[Theory]
|
||||
[InlineData(typeof(JsonContentSerializer), "application/json")]
|
||||
[InlineData(typeof(XmlContentSerializer), "application/xml")]
|
||||
public async Task MultipartUploadShouldWorkWithObjects(Type contentSerializerType, string mediaType)
|
||||
{
|
||||
if (!(Activator.CreateInstance(contentSerializerType) is IContentSerializer serializer))
|
||||
{
|
||||
throw new ArithmeticException($"{contentSerializerType.FullName} does not implement {nameof(IContentSerializer)}");
|
||||
}
|
||||
|
||||
var model1 = new ModelObject
|
||||
{
|
||||
Property1 = "M1.prop1",
|
||||
|
@ -451,7 +466,6 @@ namespace Refit.Tests
|
|||
Property1 = "M2.prop1"
|
||||
};
|
||||
|
||||
|
||||
var handler = new MockHttpMessageHandler
|
||||
{
|
||||
Asserts = async content =>
|
||||
|
@ -462,16 +476,16 @@ namespace Refit.Tests
|
|||
|
||||
Assert.Equal("theObjects", parts[0].Headers.ContentDisposition.Name);
|
||||
Assert.Null(parts[0].Headers.ContentDisposition.FileName);
|
||||
Assert.Equal("application/json", parts[0].Headers.ContentType.MediaType);
|
||||
var result0 = JsonConvert.DeserializeObject<ModelObject>(await parts[0].ReadAsStringAsync());
|
||||
Assert.Equal(mediaType, parts[0].Headers.ContentType.MediaType);
|
||||
var result0 = serializer.Deserialize<ModelObject>(await parts[0].ReadAsStringAsync());
|
||||
Assert.Equal(model1.Property1, result0.Property1);
|
||||
Assert.Equal(model1.Property2, result0.Property2);
|
||||
|
||||
|
||||
Assert.Equal("theObjects", parts[1].Headers.ContentDisposition.Name);
|
||||
Assert.Null(parts[1].Headers.ContentDisposition.FileName);
|
||||
Assert.Equal("application/json", parts[1].Headers.ContentType.MediaType);
|
||||
var result1 = JsonConvert.DeserializeObject<ModelObject>(await parts[1].ReadAsStringAsync());
|
||||
Assert.Equal(mediaType, parts[1].Headers.ContentType.MediaType);
|
||||
var result1 = serializer.Deserialize<ModelObject>(await parts[1].ReadAsStringAsync());
|
||||
Assert.Equal(model2.Property1, result1.Property1);
|
||||
Assert.Equal(model2.Property2, result1.Property2);
|
||||
}
|
||||
|
@ -479,7 +493,8 @@ namespace Refit.Tests
|
|||
|
||||
var settings = new RefitSettings()
|
||||
{
|
||||
HttpMessageHandlerFactory = () => handler
|
||||
HttpMessageHandlerFactory = () => handler,
|
||||
ContentSerializer = serializer
|
||||
};
|
||||
|
||||
var fixture = RestService.For<IRunscopeApi>(BaseAddress, settings);
|
||||
|
|
|
@ -11,6 +11,7 @@ using Xunit;
|
|||
using Refit; // InterfaceStubGenerator looks for this
|
||||
using RichardSzalay.MockHttp;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Refit.Tests
|
||||
{
|
||||
|
@ -1107,5 +1108,33 @@ namespace Refit.Tests
|
|||
|
||||
mockHttp.VerifyNoOutstandingExpectation();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanSerializeContentAsXml()
|
||||
{
|
||||
var mockHttp = new MockHttpMessageHandler();
|
||||
var contentSerializer = new XmlContentSerializer();
|
||||
var settings = new RefitSettings
|
||||
{
|
||||
HttpMessageHandlerFactory = () => mockHttp,
|
||||
ContentSerializer = contentSerializer
|
||||
};
|
||||
|
||||
mockHttp
|
||||
.Expect(HttpMethod.Post, "/users")
|
||||
.WithHeaders("Content-Type:application/xml; charset=utf-8")
|
||||
.Respond(req => new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new StringContent("<User><Name>Created</Name></User>", Encoding.UTF8, "application/xml")
|
||||
});
|
||||
|
||||
var fixture = RestService.For<IGitHubApi>("https://api.github.com", settings);
|
||||
|
||||
var result = await fixture.CreateUser(new User()).ConfigureAwait(false);
|
||||
|
||||
Assert.Equal("Created", result.Name);
|
||||
|
||||
mockHttp.VerifyNoOutstandingExpectation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using Xunit;
|
||||
|
||||
namespace Refit.Tests
|
||||
{
|
||||
public class XmlContentSerializerTests
|
||||
{
|
||||
public class Dto
|
||||
{
|
||||
public DateTime CreatedOn { get; set; }
|
||||
|
||||
public string Identifier { get; set; }
|
||||
|
||||
[XmlElement(Namespace = "https://google.com")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MediaTypeShouldBeApplicationXml()
|
||||
{
|
||||
var dto = BuildDto();
|
||||
var sut = new XmlContentSerializer();
|
||||
|
||||
var content = sut.Serialize(dto);
|
||||
|
||||
Assert.Equal("application/xml", content.Headers.ContentType.MediaType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldSerializeToXml()
|
||||
{
|
||||
var dto = BuildDto();
|
||||
var sut = new XmlContentSerializer();
|
||||
|
||||
var content = sut.Serialize(dto);
|
||||
var document = new XmlDocument();
|
||||
document.LoadXml(await content.ReadAsStringAsync());
|
||||
|
||||
var root = document[nameof(Dto)] ?? throw new NullReferenceException("Root element was not found");
|
||||
Assert.Equal(dto.CreatedOn, XmlConvert.ToDateTime(root[nameof(Dto.CreatedOn)].InnerText, XmlDateTimeSerializationMode.Utc));
|
||||
Assert.Equal(dto.Identifier, root[nameof(Dto.Identifier)].InnerText);
|
||||
Assert.Equal(dto.Name, root[nameof(Dto.Name)].InnerText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldSerializeToXmlUsingAttributeOverrides()
|
||||
{
|
||||
const string overridenRootElementName = "dto-ex";
|
||||
|
||||
var dto = BuildDto();
|
||||
var serializerSettings = new XmlContentSerializerSettings();
|
||||
var attributes = new XmlAttributes { XmlRoot = new XmlRootAttribute(overridenRootElementName) };
|
||||
serializerSettings.XmlAttributeOverrides.Add(dto.GetType(), attributes);
|
||||
var sut = new XmlContentSerializer(serializerSettings);
|
||||
|
||||
var content = sut.Serialize(dto);
|
||||
var document = new XmlDocument();
|
||||
document.LoadXml(await content.ReadAsStringAsync());
|
||||
|
||||
Assert.Equal(overridenRootElementName, document.DocumentElement?.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldSerializeToXmlUsingNamespaceOverrides()
|
||||
{
|
||||
const string prefix = "google";
|
||||
|
||||
var dto = BuildDto();
|
||||
var serializerSettings = new XmlContentSerializerSettings { XmlNamespaces = new XmlSerializerNamespaces() };
|
||||
serializerSettings.XmlNamespaces.Add(prefix, "https://google.com");
|
||||
var sut = new XmlContentSerializer(serializerSettings);
|
||||
|
||||
var content = sut.Serialize(dto);
|
||||
var document = new XmlDocument();
|
||||
document.LoadXml(await content.ReadAsStringAsync());
|
||||
|
||||
Assert.Equal(prefix, document["Dto"]?["Name", "https://google.com"]?.Prefix);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDeserializeFromXml()
|
||||
{
|
||||
var serializerSettings = new XmlContentSerializerSettings { XmlNamespaces = new XmlSerializerNamespaces() };
|
||||
var sut = new XmlContentSerializer(serializerSettings);
|
||||
|
||||
var dto = sut.Deserialize<Dto>("<Dto><Identifier>123</Identifier></Dto>");
|
||||
|
||||
Assert.Equal("123", dto.Identifier);
|
||||
}
|
||||
|
||||
private static Dto BuildDto()
|
||||
{
|
||||
var dto = new Dto {
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
Identifier = Guid.NewGuid().ToString(),
|
||||
Name = "Test Dto Object"
|
||||
};
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
@ -17,11 +18,8 @@ namespace Refit
|
|||
public HttpMethod HttpMethod { get; }
|
||||
public Uri Uri => RequestMessage.RequestUri;
|
||||
public HttpRequestMessage RequestMessage { get; }
|
||||
|
||||
public HttpContentHeaders ContentHeaders { get; private set; }
|
||||
|
||||
public string Content { get; private set; }
|
||||
|
||||
public bool HasContent => !string.IsNullOrWhiteSpace(Content);
|
||||
public RefitSettings RefitSettings { get; set; }
|
||||
|
||||
|
@ -37,7 +35,7 @@ namespace Refit
|
|||
}
|
||||
|
||||
public T GetContentAs<T>() => HasContent ?
|
||||
JsonConvert.DeserializeObject<T>(Content, RefitSettings.JsonSerializerSettings) :
|
||||
RefitSettings.ContentSerializer.Deserialize<T>(Content) :
|
||||
default;
|
||||
|
||||
#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Refit {
|
||||
|
||||
public class JsonContentSerializer : IContentSerializer
|
||||
{
|
||||
private readonly JsonSerializerSettings jsonSerializerSettings;
|
||||
|
||||
public JsonContentSerializer() : this(new JsonSerializerSettings())
|
||||
{
|
||||
}
|
||||
|
||||
public JsonContentSerializer(JsonSerializerSettings jsonSerializerSettings)
|
||||
{
|
||||
this.jsonSerializerSettings = jsonSerializerSettings ?? throw new ArgumentNullException(nameof(jsonSerializerSettings));
|
||||
}
|
||||
|
||||
public HttpContent Serialize(object item)
|
||||
{
|
||||
return new StringContent(JsonConvert.SerializeObject(item, jsonSerializerSettings), Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
public async Task<object> DeserializeAsync(HttpContent content, Type objectType)
|
||||
{
|
||||
var serializer = JsonSerializer.Create(jsonSerializerSettings);
|
||||
|
||||
using (var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using (var reader = new StreamReader(stream))
|
||||
using (var jsonTextReader = new JsonTextReader(reader))
|
||||
return serializer.Deserialize(jsonTextReader, objectType);
|
||||
}
|
||||
|
||||
public T Deserialize<T>(string content)
|
||||
{
|
||||
var serializer = JsonSerializer.Create(jsonSerializerSettings);
|
||||
|
||||
using (var reader = new StringReader(content))
|
||||
using (var jsonTextReader = new JsonTextReader(reader))
|
||||
return serializer.Deserialize<T>(jsonTextReader);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.4' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="1.1.2" />
|
||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.5.0" />
|
||||
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0 " />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
@ -13,21 +12,43 @@ namespace Refit
|
|||
{
|
||||
public class RefitSettings
|
||||
{
|
||||
JsonSerializerSettings jsonSerializerSettings;
|
||||
|
||||
public RefitSettings()
|
||||
{
|
||||
UrlParameterFormatter = new DefaultUrlParameterFormatter();
|
||||
FormUrlEncodedParameterFormatter = new DefaultFormUrlEncodedParameterFormatter();
|
||||
ContentSerializer = new JsonContentSerializer();
|
||||
}
|
||||
|
||||
public Func<Task<string>> AuthorizationHeaderValueGetter { get; set; }
|
||||
public Func<HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
|
||||
|
||||
public JsonSerializerSettings JsonSerializerSettings { get; set; }
|
||||
public JsonSerializerSettings JsonSerializerSettings
|
||||
{
|
||||
get => jsonSerializerSettings;
|
||||
set
|
||||
{
|
||||
jsonSerializerSettings = value;
|
||||
ContentSerializer = new JsonContentSerializer(value);
|
||||
}
|
||||
}
|
||||
|
||||
public IContentSerializer ContentSerializer { get; set; }
|
||||
public IUrlParameterFormatter UrlParameterFormatter { get; set; }
|
||||
public IFormUrlEncodedParameterFormatter FormUrlEncodedParameterFormatter { get; set; }
|
||||
public bool Buffered { get; set; } = true;
|
||||
}
|
||||
|
||||
public interface IContentSerializer
|
||||
{
|
||||
HttpContent Serialize(object item);
|
||||
|
||||
Task<object> DeserializeAsync(HttpContent content, Type objectType);
|
||||
|
||||
T Deserialize<T>(string content);
|
||||
}
|
||||
|
||||
public interface IUrlParameterFormatter
|
||||
{
|
||||
string Format(object value, ParameterInfo parameterInfo);
|
||||
|
|
|
@ -10,7 +10,6 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
|
@ -25,7 +24,7 @@ namespace Refit
|
|||
};
|
||||
readonly Dictionary<string, List<RestMethodInfo>> interfaceHttpMethods;
|
||||
readonly ConcurrentDictionary<CloseGenericMethodKey, RestMethodInfo> interfaceGenericHttpMethods;
|
||||
readonly JsonSerializer serializer;
|
||||
readonly IContentSerializer serializer;
|
||||
readonly RefitSettings settings;
|
||||
public Type TargetType { get; }
|
||||
|
||||
|
@ -34,7 +33,7 @@ namespace Refit
|
|||
Type targetInterface = typeof(TApi);
|
||||
|
||||
settings = refitSettings ?? new RefitSettings();
|
||||
serializer = JsonSerializer.Create(settings.JsonSerializerSettings);
|
||||
serializer = settings.ContentSerializer;
|
||||
interfaceGenericHttpMethods = new ConcurrentDictionary<CloseGenericMethodKey, RestMethodInfo>();
|
||||
|
||||
if (targetInterface == null || !targetInterface.GetTypeInfo().IsInterface)
|
||||
|
@ -201,8 +200,7 @@ namespace Refit
|
|||
Exception e = null;
|
||||
try
|
||||
{
|
||||
var stringContent = new StringContent(JsonConvert.SerializeObject(itemValue, settings.JsonSerializerSettings), Encoding.UTF8, "application/json");
|
||||
multiPartContent.Add(stringContent, parameterName);
|
||||
multiPartContent.Add(settings.ContentSerializer.Serialize(itemValue), parameterName);
|
||||
return;
|
||||
}
|
||||
catch(Exception ex)
|
||||
|
@ -277,25 +275,26 @@ namespace Refit
|
|||
return (T)stream;
|
||||
}
|
||||
|
||||
using (var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using (var reader = new StreamReader(stream))
|
||||
if (serializedReturnType == typeof(string))
|
||||
{
|
||||
if (serializedReturnType == typeof(string))
|
||||
using(var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using(var reader = new StreamReader(stream))
|
||||
{
|
||||
var str = (object)await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||
if (isApiResponse)
|
||||
return ApiResponse.Create<T>(resp, str);
|
||||
return (T)str;
|
||||
}
|
||||
if (serializedReturnType == typeof(string))
|
||||
{
|
||||
var str = (object)await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||
if (isApiResponse)
|
||||
return ApiResponse.Create<T>(resp, str);
|
||||
return (T)str;
|
||||
}
|
||||
|
||||
using (var jsonReader = new JsonTextReader(reader))
|
||||
{
|
||||
var json = serializer.Deserialize(jsonReader, serializedReturnType);
|
||||
if (isApiResponse)
|
||||
return ApiResponse.Create<T>(resp, json);
|
||||
return (T)json;
|
||||
}
|
||||
}
|
||||
|
||||
var json = await serializer.DeserializeAsync(content, serializedReturnType);
|
||||
if (isApiResponse)
|
||||
return ApiResponse.Create<T>(resp, json);
|
||||
return (T)json;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -467,24 +466,15 @@ namespace Refit
|
|||
break;
|
||||
case BodySerializationMethod.Default:
|
||||
case BodySerializationMethod.Json:
|
||||
var param = paramList[i];
|
||||
var content = serializer.Serialize(paramList[i]);
|
||||
switch (restMethod.BodyParameterInfo.Item2)
|
||||
{
|
||||
case false:
|
||||
ret.Content = new PushStreamContent((stream, _, __) =>
|
||||
{
|
||||
using (var writer = new JsonTextWriter(new StreamWriter(stream)))
|
||||
{
|
||||
serializer.Serialize(writer, param);
|
||||
}
|
||||
},
|
||||
new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" });
|
||||
ret.Content = new PushStreamContent(
|
||||
async (stream, _, __) => { await content.CopyToAsync(stream).ConfigureAwait(false); }, content.Headers.ContentType);
|
||||
break;
|
||||
case true:
|
||||
ret.Content = new StringContent(
|
||||
JsonConvert.SerializeObject(paramList[i], settings.JsonSerializerSettings),
|
||||
Encoding.UTF8,
|
||||
"application/json");
|
||||
ret.Content = content;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Refit {
|
||||
|
||||
public class XmlContentSerializer : IContentSerializer
|
||||
{
|
||||
private readonly XmlContentSerializerSettings settings;
|
||||
|
||||
public XmlContentSerializer() : this(new XmlContentSerializerSettings())
|
||||
{
|
||||
}
|
||||
|
||||
public XmlContentSerializer(XmlContentSerializerSettings settings)
|
||||
{
|
||||
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
public HttpContent Serialize(object item)
|
||||
{
|
||||
var xmlSerializer = new XmlSerializer(item.GetType(), settings.XmlAttributeOverrides);
|
||||
|
||||
using(var output = new StringWriter())
|
||||
{
|
||||
using(var writer = XmlWriter.Create(output, settings.XmlReaderWriterSettings.WriterSettings))
|
||||
{
|
||||
xmlSerializer.Serialize(writer, item, settings.XmlNamespaces);
|
||||
return new StringContent(output.ToString(), Encoding.UTF8, "application/xml");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<object> DeserializeAsync(HttpContent content, Type objectType)
|
||||
{
|
||||
var xmlSerializer = new XmlSerializer(objectType, settings.XmlAttributeOverrides);
|
||||
|
||||
using (var input = new StringReader(await content.ReadAsStringAsync().ConfigureAwait(false)))
|
||||
{
|
||||
using (var reader = XmlReader.Create(input, settings.XmlReaderWriterSettings.ReaderSettings))
|
||||
{
|
||||
return xmlSerializer.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T Deserialize<T>(string content)
|
||||
{
|
||||
var xmlSerializer = new XmlSerializer(typeof(T), settings.XmlAttributeOverrides);
|
||||
|
||||
using (var input = new StringReader(content))
|
||||
{
|
||||
using (var reader = XmlReader.Create(input, settings.XmlReaderWriterSettings.ReaderSettings))
|
||||
{
|
||||
return (T)(object)xmlSerializer.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class XmlReaderWriterSettings
|
||||
{
|
||||
private XmlReaderSettings readerSettings;
|
||||
private XmlWriterSettings writerSettings;
|
||||
|
||||
public XmlReaderWriterSettings() : this(new XmlReaderSettings(), new XmlWriterSettings())
|
||||
{
|
||||
}
|
||||
|
||||
public XmlReaderWriterSettings(XmlReaderSettings readerSettings) : this(readerSettings, new XmlWriterSettings())
|
||||
{
|
||||
}
|
||||
|
||||
public XmlReaderWriterSettings(XmlWriterSettings writerSettings) : this(new XmlReaderSettings(), writerSettings)
|
||||
{
|
||||
}
|
||||
|
||||
public XmlReaderWriterSettings(XmlReaderSettings readerSettings, XmlWriterSettings writerSettings)
|
||||
{
|
||||
ReaderSettings = readerSettings;
|
||||
WriterSettings = writerSettings;
|
||||
}
|
||||
|
||||
public XmlReaderSettings ReaderSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
ApplyOverrideSettings();
|
||||
return readerSettings;
|
||||
}
|
||||
set => readerSettings = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
public XmlWriterSettings WriterSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
ApplyOverrideSettings();
|
||||
return writerSettings;
|
||||
}
|
||||
set => writerSettings = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The writer and reader settings are set by the caller, but certain properties
|
||||
/// should remain set to meet the demands of the XmlContentSerializer. Those properties
|
||||
/// are always set here.
|
||||
/// </summary>
|
||||
private void ApplyOverrideSettings()
|
||||
{
|
||||
writerSettings.Async = true;
|
||||
readerSettings.Async = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class XmlContentSerializerSettings
|
||||
{
|
||||
public XmlContentSerializerSettings()
|
||||
{
|
||||
XmlReaderWriterSettings = new XmlReaderWriterSettings();
|
||||
XmlNamespaces = new XmlSerializerNamespaces(
|
||||
new[]
|
||||
{
|
||||
new XmlQualifiedName(string.Empty, string.Empty),
|
||||
});
|
||||
|
||||
XmlAttributeOverrides = new XmlAttributeOverrides();
|
||||
}
|
||||
|
||||
public XmlReaderWriterSettings XmlReaderWriterSettings { get; set; }
|
||||
|
||||
public XmlSerializerNamespaces XmlNamespaces { get; set; }
|
||||
|
||||
public XmlAttributeOverrides XmlAttributeOverrides { get; set; }
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче