Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Andrew Arnott 2019-01-17 22:48:09 -08:00
Родитель 8ad71917ae 2d94755f9e
Коммит 2e690fe998
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A9B9910CDCCDA441
13 изменённых файлов: 858 добавлений и 225 удалений

Просмотреть файл

@ -57,6 +57,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{301F812B
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessagePack.UniversalCodeGenerator", "src\MessagePack.UniversalCodeGenerator\MessagePack.UniversalCodeGenerator.csproj", "{10AD85DD-929D-49B8-BD43-45242C2644B7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MessagePack.AspNetCoreMvcFormatter.Tests", "tests\MessagePack.AspNetCoreMvcFormatter.Tests\MessagePack.AspNetCoreMvcFormatter.Tests.csproj", "{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -247,6 +249,18 @@ Global
{10AD85DD-929D-49B8-BD43-45242C2644B7}.Release|x64.Build.0 = Release|Any CPU
{10AD85DD-929D-49B8-BD43-45242C2644B7}.Release|x86.ActiveCfg = Release|Any CPU
{10AD85DD-929D-49B8-BD43-45242C2644B7}.Release|x86.Build.0 = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|Any CPU.Build.0 = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|x64.ActiveCfg = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|x64.Build.0 = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|x86.ActiveCfg = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Debug|x86.Build.0 = Debug|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|Any CPU.ActiveCfg = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|Any CPU.Build.0 = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|x64.ActiveCfg = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|x64.Build.0 = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|x86.ActiveCfg = Release|Any CPU
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -267,6 +281,7 @@ Global
{814F94D6-1413-4ACB-B1B5-A3488CAA1E6B} = {BF4C4202-5015-4FBD-80E6-D0F36A06F700}
{2A32A538-BA26-4D89-85D0-E4249AFA0837} = {BF4C4202-5015-4FBD-80E6-D0F36A06F700}
{10AD85DD-929D-49B8-BD43-45242C2644B7} = {86309CF6-0054-4CE3-BFD3-CA0AA7DB17BC}
{79C2B2CB-872A-4BA9-82DC-60F6DD77F940} = {19FE674A-AC94-4E7E-B24C-2285D1D04CDE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {26F0752B-06F7-44AD-BFEE-8F2E36B3AA27}

Просмотреть файл

@ -1,104 +0,0 @@
using Microsoft.AspNetCore.Mvc.Formatters;
using System.Threading.Tasks;
namespace MessagePack.AspNetCoreMvcFormatter
{
public class MessagePackOutputFormatter : IOutputFormatter //, IApiResponseTypeMetadataProvider
{
const string ContentType = "application/x-msgpack";
static readonly string[] SupportedContentTypes = new[] { ContentType };
readonly MessagePackSerializer.NonGeneric serializer;
public MessagePackOutputFormatter()
: this((IFormatterResolver)null)
{
}
public MessagePackOutputFormatter(IFormatterResolver resolver)
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer(resolver)))
{
}
public MessagePackOutputFormatter(MessagePackSerializer.NonGeneric serializer)
{
this.serializer = serializer ?? new MessagePackSerializer.NonGeneric(new MessagePackSerializer());
}
//public IReadOnlyList<string> GetSupportedContentTypes(string contentType, Type objectType)
//{
// return SupportedContentTypes;
//}
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
return true;
}
public Task WriteAsync(OutputFormatterWriteContext context)
{
context.HttpContext.Response.ContentType = ContentType;
// 'object' want to use anonymous type serialize, etc...
if (context.ObjectType == typeof(object))
{
if (context.Object == null)
{
context.HttpContext.Response.Body.WriteByte(MessagePackCode.Nil);
return Task.CompletedTask;
}
else
{
// use concrete type.
serializer.Serialize(context.Object.GetType(), context.HttpContext.Response.Body, context.Object);
return Task.CompletedTask;
}
}
else
{
serializer.Serialize(context.ObjectType, context.HttpContext.Response.Body, context.Object);
return Task.CompletedTask;
}
}
}
public class MessagePackInputFormatter : IInputFormatter // , IApiRequestFormatMetadataProvider
{
const string ContentType = "application/x-msgpack";
static readonly string[] SupportedContentTypes = new[] { ContentType };
readonly MessagePackSerializer.NonGeneric serializer;
public MessagePackInputFormatter()
: this((IFormatterResolver)null)
{
}
public MessagePackInputFormatter(IFormatterResolver resolver)
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer(resolver)))
{
}
public MessagePackInputFormatter(MessagePackSerializer.NonGeneric serializer)
{
this.serializer = serializer ?? new MessagePackSerializer.NonGeneric(new MessagePackSerializer());
}
//public IReadOnlyList<string> GetSupportedContentTypes(string contentType, Type objectType)
//{
// return SupportedContentTypes;
//}
public bool CanRead(InputFormatterContext context)
{
return true;
}
public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
var result = serializer.Deserialize(context.ModelType, request.Body);
return InputFormatterResult.SuccessAsync(result);
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
namespace MessagePack.AspNetCoreMvcFormatter
{
public class LZ4MessagePackInputFormatter : MessagePackInputFormatter
{
public LZ4MessagePackInputFormatter()
: base(new LZ4MessagePackSerializer.NonGeneric())
{
}
public LZ4MessagePackInputFormatter(IFormatterResolver resolver)
: base(new LZ4MessagePackSerializer.NonGeneric(resolver))
{
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
namespace MessagePack.AspNetCoreMvcFormatter
{
public class LZ4MessagePackOutputFormatter : MessagePackOutputFormatter
{
public LZ4MessagePackOutputFormatter()
: base(new LZ4MessagePackSerializer.NonGeneric())
{
}
public LZ4MessagePackOutputFormatter(IFormatterResolver resolver)
: base(new LZ4MessagePackSerializer.NonGeneric(resolver))
{
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
namespace MessagePack.AspNetCoreMvcFormatter
{
public class MessagePackInputFormatter : IInputFormatter
{
private const string ContentType = "application/x-msgpack";
private readonly MessagePackSerializer.NonGeneric serializer;
public MessagePackInputFormatter()
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer()))
{
}
public MessagePackInputFormatter(IFormatterResolver resolver)
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer(resolver)))
{
}
public MessagePackInputFormatter(MessagePackSerializer.NonGeneric serializer)
{
this.serializer = serializer ?? new MessagePackSerializer.NonGeneric();
}
public bool CanRead(InputFormatterContext context) =>
context.HttpContext.Request.ContentType == ContentType;
public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
var result = this.serializer.Deserialize(context.ModelType, request.Body);
return InputFormatterResult.SuccessAsync(result);
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;
namespace MessagePack.AspNetCoreMvcFormatter
{
public class MessagePackOutputFormatter : IOutputFormatter
{
private const string ContentType = "application/x-msgpack";
private readonly MessagePackSerializer.NonGeneric serializer;
public MessagePackOutputFormatter()
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer()))
{
}
public MessagePackOutputFormatter(IFormatterResolver resolver)
: this(new MessagePackSerializer.NonGeneric(new MessagePackSerializer(resolver)))
{
}
public MessagePackOutputFormatter(MessagePackSerializer.NonGeneric serializer)
{
this.serializer = serializer ?? new MessagePackSerializer.NonGeneric();
}
public bool CanWriteResult(OutputFormatterCanWriteContext context) =>
context.HttpContext.Request.ContentType == ContentType;
public Task WriteAsync(OutputFormatterWriteContext context)
{
context.HttpContext.Response.ContentType = ContentType;
if (context.ObjectType == typeof(object))
{
if (context.Object == null)
{
context.HttpContext.Response.Body.WriteByte(MessagePackCode.Nil);
return Task.CompletedTask;
}
else
{
this.serializer.Serialize(context.Object.GetType(), context.HttpContext.Response.Body, context.Object);
return Task.CompletedTask;
}
}
else
{
this.serializer.Serialize(context.ObjectType, context.HttpContext.Response.Body, context.Object);
return Task.CompletedTask;
}
}
}
}

Просмотреть файл

@ -327,7 +327,7 @@ namespace MessagePack.CodeGenerator
var unionAttrs = type.GetAttributes().Where(x => x.AttributeClass == typeReferences.UnionAttribute).Select(x => x.ConstructorArguments).ToArray();
if (unionAttrs.Length == 0)
{
throw new MessagePackGeneratorResolveFailedException("Serialization Type must mark UnionAttribute." + " type: " + type.Name);
throw new MessagePackGeneratorResolveFailedException("Serialization Type must mark UnionAttribute." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
// 0, Int 1, SubType
@ -466,7 +466,7 @@ namespace MessagePack.CodeGenerator
var contractAttr = type.GetAttributes().FirstOrDefault(x => x.AttributeClass == typeReferences.MessagePackObjectAttribute);
if (contractAttr == null)
{
throw new MessagePackGeneratorResolveFailedException("Serialization Object must mark MessagePackObjectAttribute." + " type: " + type.Name);
throw new MessagePackGeneratorResolveFailedException("Serialization Object must mark MessagePackObjectAttribute." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
var isIntKey = true;
@ -546,11 +546,11 @@ namespace MessagePack.CodeGenerator
if (!member.IsReadable && !member.IsWritable) continue;
var key = item.GetAttributes().FirstOrDefault(x => x.AttributeClass == typeReferences.KeyAttribute)?.ConstructorArguments[0];
if (key == null) throw new MessagePackGeneratorResolveFailedException("all public members must mark KeyAttribute or IgnoreMemberAttribute." + " type: " + type.Name + " member:" + item.Name);
if (key == null) throw new MessagePackGeneratorResolveFailedException("all public members must mark KeyAttribute or IgnoreMemberAttribute." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
var intKey = (key.Value.Value is int) ? (int)key.Value.Value : (int?)null;
var stringKey = (key.Value.Value is string) ? (string)key.Value.Value : (string)null;
if (intKey == null && stringKey == null) throw new MessagePackGeneratorResolveFailedException("both IntKey and StringKey are null." + " type: " + type.Name + " member:" + item.Name);
if (intKey == null && stringKey == null) throw new MessagePackGeneratorResolveFailedException("both IntKey and StringKey are null." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
if (searchFirst)
{
@ -561,21 +561,21 @@ namespace MessagePack.CodeGenerator
{
if ((isIntKey && intKey == null) || (!isIntKey && stringKey == null))
{
throw new MessagePackGeneratorResolveFailedException("all members key type must be same." + " type: " + type.Name + " member:" + item.Name);
throw new MessagePackGeneratorResolveFailedException("all members key type must be same." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
}
}
if (isIntKey)
{
member.IntKey = (int)intKey;
if (intMemebrs.ContainsKey(member.IntKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.Name + " member:" + item.Name);
if (intMemebrs.ContainsKey(member.IntKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
intMemebrs.Add(member.IntKey, member);
}
else
{
member.StringKey = (string)stringKey;
if (stringMembers.ContainsKey(member.StringKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.Name + " member:" + item.Name);
if (stringMembers.ContainsKey(member.StringKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
member.IntKey = hiddenIntKey++;
stringMembers.Add(member.StringKey, member);
@ -602,11 +602,11 @@ namespace MessagePack.CodeGenerator
if (!member.IsReadable && !member.IsWritable) continue;
var key = item.GetAttributes().FirstOrDefault(x => x.AttributeClass == typeReferences.KeyAttribute)?.ConstructorArguments[0];
if (key == null) throw new MessagePackGeneratorResolveFailedException("all public members must mark KeyAttribute or IgnoreMemberAttribute." + " type: " + type.Name + " member:" + item.Name);
if (key == null) throw new MessagePackGeneratorResolveFailedException("all public members must mark KeyAttribute or IgnoreMemberAttribute." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
var intKey = (key.Value.Value is int) ? (int)key.Value.Value : (int?)null;
var stringKey = (key.Value.Value is string) ? (string)key.Value.Value : (string)null;
if (intKey == null && stringKey == null) throw new MessagePackGeneratorResolveFailedException("both IntKey and StringKey are null." + " type: " + type.Name + " member:" + item.Name);
if (intKey == null && stringKey == null) throw new MessagePackGeneratorResolveFailedException("both IntKey and StringKey are null." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
if (searchFirst)
{
@ -624,14 +624,14 @@ namespace MessagePack.CodeGenerator
if (isIntKey)
{
member.IntKey = (int)intKey;
if (intMemebrs.ContainsKey(member.IntKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.Name + " member:" + item.Name);
if (intMemebrs.ContainsKey(member.IntKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
intMemebrs.Add(member.IntKey, member);
}
else
{
member.StringKey = (string)stringKey;
if (stringMembers.ContainsKey(member.StringKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.Name + " member:" + item.Name);
if (stringMembers.ContainsKey(member.StringKey)) throw new MessagePackGeneratorResolveFailedException("key is duplicated, all members key must be unique." + " type: " + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " member:" + item.Name);
member.IntKey = hiddenIntKey++;
stringMembers.Add(member.StringKey, member);
@ -658,7 +658,7 @@ namespace MessagePack.CodeGenerator
}
// struct allows null ctor
if (ctor == null && isClass) throw new MessagePackGeneratorResolveFailedException("can't find public constructor. type:" + type.Name);
if (ctor == null && isClass) throw new MessagePackGeneratorResolveFailedException("can't find public constructor. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
var constructorParameters = new List<MemberSerializationInfo>();
if (ctor != null)
@ -688,7 +688,7 @@ namespace MessagePack.CodeGenerator
}
else
{
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, parameterType mismatch. type:" + type.Name + " parameterIndex:" + ctorParamIndex + " paramterType:" + item.Type.Name);
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, parameterType mismatch. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " parameterIndex:" + ctorParamIndex + " paramterType:" + item.Type.Name);
}
}
}
@ -701,7 +701,7 @@ namespace MessagePack.CodeGenerator
}
else
{
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, index not found. type:" + type.Name + " parameterIndex:" + ctorParamIndex);
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, index not found. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " parameterIndex:" + ctorParamIndex);
}
}
}
@ -720,7 +720,7 @@ namespace MessagePack.CodeGenerator
}
else
{
throw new MessagePackGeneratorResolveFailedException("duplicate matched constructor parameter name:" + type.Name + " parameterName:" + item.Name + " paramterType:" + item.Type.Name);
throw new MessagePackGeneratorResolveFailedException("duplicate matched constructor parameter name:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " parameterName:" + item.Name + " paramterType:" + item.Type.Name);
}
}
@ -738,7 +738,7 @@ namespace MessagePack.CodeGenerator
}
else
{
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, parameterType mismatch. type:" + type.Name + " parameterName:" + item.Name + " paramterType:" + item.Type.Name);
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, parameterType mismatch. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " parameterName:" + item.Name + " paramterType:" + item.Type.Name);
}
}
}
@ -751,7 +751,7 @@ namespace MessagePack.CodeGenerator
}
else
{
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, index not found. type:" + type.Name + " parameterName:" + item.Name);
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor parameter, index not found. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + " parameterName:" + item.Name);
}
}
}
@ -761,7 +761,7 @@ namespace MessagePack.CodeGenerator
if (ctor == null)
{
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor. type:" + type.Name);
throw new MessagePackGeneratorResolveFailedException("can't find matched constructor. type:" + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
}
}

Просмотреть файл

@ -6,7 +6,6 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MessagePack.CodeGenerator
{
@ -56,7 +55,7 @@ namespace MessagePack.CodeGenerator
return;
}
SHOW_HELP:
SHOW_HELP:
Console.WriteLine("mpc arguments help:");
option.WriteOptionDescriptions(Console.Out);
IsParsed = false;
@ -71,93 +70,102 @@ namespace MessagePack.CodeGenerator
class Program
{
static void Main(string[] args)
static int Main(string[] args)
{
var cmdArgs = new CommandlineArguments(args);
if (!cmdArgs.IsParsed)
try
{
return;
}
// Generator Start...
var sw = Stopwatch.StartNew();
Console.WriteLine("Project Compilation Start:" + cmdArgs.InputPath);
var collector = new TypeCollector(cmdArgs.InputPath, cmdArgs.ConditionalSymbols, true, cmdArgs.IsUseMap);
Console.WriteLine("Project Compilation Complete:" + sw.Elapsed.ToString());
Console.WriteLine();
sw.Restart();
Console.WriteLine("Method Collect Start");
var (objectInfo, enumInfo, genericInfo, unionInfo) = collector.Collect();
Console.WriteLine("Method Collect Complete:" + sw.Elapsed.ToString());
Console.WriteLine("Output Generation Start");
sw.Restart();
var objectFormatterTemplates = objectInfo
.GroupBy(x => x.Namespace)
.Select(x => new FormatterTemplate()
var cmdArgs = new CommandlineArguments(args);
if (!cmdArgs.IsParsed)
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
objectSerializationInfos = x.ToArray(),
})
.ToArray();
return 0;
}
var enumFormatterTemplates = enumInfo
.GroupBy(x => x.Namespace)
.Select(x => new EnumTemplate()
// Generator Start...
var sw = Stopwatch.StartNew();
Console.WriteLine("Project Compilation Start:" + cmdArgs.InputPath);
var collector = new TypeCollector(cmdArgs.InputPath, cmdArgs.ConditionalSymbols, true, cmdArgs.IsUseMap);
Console.WriteLine("Project Compilation Complete:" + sw.Elapsed.ToString());
Console.WriteLine();
sw.Restart();
Console.WriteLine("Method Collect Start");
var (objectInfo, enumInfo, genericInfo, unionInfo) = collector.Collect();
Console.WriteLine("Method Collect Complete:" + sw.Elapsed.ToString());
Console.WriteLine("Output Generation Start");
sw.Restart();
var objectFormatterTemplates = objectInfo
.GroupBy(x => x.Namespace)
.Select(x => new FormatterTemplate()
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
objectSerializationInfos = x.ToArray(),
})
.ToArray();
var enumFormatterTemplates = enumInfo
.GroupBy(x => x.Namespace)
.Select(x => new EnumTemplate()
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
enumSerializationInfos = x.ToArray()
})
.ToArray();
var unionFormatterTemplates = unionInfo
.GroupBy(x => x.Namespace)
.Select(x => new UnionTemplate()
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
unionSerializationInfos = x.ToArray()
})
.ToArray();
var resolverTemplate = new ResolverTemplate()
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
enumSerializationInfos = x.ToArray()
})
.ToArray();
Namespace = cmdArgs.GetNamespaceDot() + "Resolvers",
FormatterNamespace = cmdArgs.GetNamespaceDot() + "Formatters",
ResolverName = cmdArgs.ResolverName,
registerInfos = genericInfo.Cast<IResolverRegisterInfo>().Concat(enumInfo).Concat(unionInfo).Concat(objectInfo).ToArray()
};
var unionFormatterTemplates = unionInfo
.GroupBy(x => x.Namespace)
.Select(x => new UnionTemplate()
var sb = new StringBuilder();
sb.AppendLine(resolverTemplate.TransformText());
sb.AppendLine();
foreach (var item in enumFormatterTemplates)
{
Namespace = cmdArgs.GetNamespaceDot() + "Formatters" + ((x.Key == null) ? "" : "." + x.Key),
unionSerializationInfos = x.ToArray()
})
.ToArray();
var text = item.TransformText();
sb.AppendLine(text);
}
sb.AppendLine();
foreach (var item in unionFormatterTemplates)
{
var text = item.TransformText();
sb.AppendLine(text);
}
sb.AppendLine();
foreach (var item in objectFormatterTemplates)
{
var text = item.TransformText();
sb.AppendLine(text);
}
var resolverTemplate = new ResolverTemplate()
{
Namespace = cmdArgs.GetNamespaceDot() + "Resolvers",
FormatterNamespace = cmdArgs.GetNamespaceDot() + "Formatters",
ResolverName = cmdArgs.ResolverName,
registerInfos = genericInfo.Cast<IResolverRegisterInfo>().Concat(enumInfo).Concat(unionInfo).Concat(objectInfo).ToArray()
};
Output(cmdArgs.OutputPath, sb.ToString());
var sb = new StringBuilder();
sb.AppendLine(resolverTemplate.TransformText());
sb.AppendLine();
foreach (var item in enumFormatterTemplates)
{
var text = item.TransformText();
sb.AppendLine(text);
Console.WriteLine("String Generation Complete:" + sw.Elapsed.ToString());
return 0;
}
sb.AppendLine();
foreach (var item in unionFormatterTemplates)
catch (Exception ex)
{
var text = item.TransformText();
sb.AppendLine(text);
Console.WriteLine("Unhandled Error:" + ex);
return 1;
}
sb.AppendLine();
foreach (var item in objectFormatterTemplates)
{
var text = item.TransformText();
sb.AppendLine(text);
}
Output(cmdArgs.OutputPath, sb.ToString());
Console.WriteLine("String Generation Complete:" + sw.Elapsed.ToString());
}
static void Output(string path, string text)

Просмотреть файл

@ -0,0 +1,130 @@
using System.Diagnostics;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MessagePack.CodeGenerator
{
internal static class ProcessUtil
{
public static async Task<int> ExecuteProcessAsync(string fileName, string args, Stream stdout, Stream stderr, TextReader stdin, CancellationToken ct = default(CancellationToken))
{
var psi = new ProcessStartInfo(fileName, args);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardError = stderr != null;
psi.RedirectStandardOutput = stdout != null;
psi.RedirectStandardInput = stdin != null;
using (var proc = new Process())
using (var cts = new CancellationTokenSource())
using (var exitedct = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, ct))
{
proc.StartInfo = psi;
proc.EnableRaisingEvents = true;
proc.Exited += (sender, ev) =>
{
cts.Cancel();
};
if (!proc.Start())
{
throw new InvalidOperationException($"failed to start process(fileName = {fileName}, args = {args})");
}
int exitCode = 0;
await Task.WhenAll(
Task.Run(() =>
{
exitCode = StdinTask(proc, stdin, exitedct, cts);
if(exitCode < 0)
{
proc.Dispose();
}
})
,
Task.Run(async () =>
{
if (stdout != null)
{
await RedirectOutputTask(proc.StandardOutput.BaseStream, stdout, exitedct.Token, "stdout");
}
})
,
Task.Run(async () =>
{
if (stderr != null)
{
await RedirectOutputTask(proc.StandardError.BaseStream, stderr, exitedct.Token, "stderr");
}
})
);
if(exitCode >= 0)
{
return proc.ExitCode;
}
else
{
return -1;
}
}
}
static int StdinTask(Process proc, TextReader stdin, CancellationTokenSource exitedct, CancellationTokenSource cts)
{
if (stdin != null)
{
while (!exitedct.Token.IsCancellationRequested)
{
var l = stdin.ReadLine();
if (l == null)
{
break;
}
proc.StandardInput.WriteLine(l);
}
proc.StandardInput.Dispose();
}
exitedct.Token.WaitHandle.WaitOne();
if (cts.IsCancellationRequested)
{
proc.WaitForExit();
var exitCode = proc.ExitCode;
return exitCode;
}
else
{
proc.StandardOutput.Dispose();
proc.StandardError.Dispose();
proc.Kill();
return -1;
}
}
static async Task RedirectOutputTask(Stream procStdout, Stream stdout, CancellationToken ct, string suffix)
{
if (stdout != null)
{
var buf = new byte[1024];
while (!ct.IsCancellationRequested)
{
try
{
var bytesread = await procStdout.ReadAsync(buf, 0, 1024, ct).ConfigureAwait(false);
if(bytesread <= 0)
{
break;
}
stdout.Write(buf, 0, bytesread);
}
catch(NullReferenceException)
{
break;
}
catch(ObjectDisposedException)
{
break;
}
}
}
}
}
}

Просмотреть файл

@ -17,6 +17,103 @@ namespace MessagePack.CodeGenerator
// Utility and Extension methods for Roslyn
internal static class RoslynExtensions
{
static (string fname, string args) GetBuildCommandLine(string csprojPath, string tempPath, bool useDotNet)
{
string fname = "dotnet";
const string tasks = "ResolveAssemblyReferencesDesignTime;ResolveProjectReferencesDesignTime;ResolveComReferencesDesignTime;Compile";
// from Buildalyzer implementation
// https://github.com/daveaglick/Buildalyzer/blob/b42d2e3ba1b3673a8133fb41e72b507b01bce1d6/src/Buildalyzer/Environment/BuildEnvironment.cs#L86-L96
Dictionary<string, string> properties = new Dictionary<string, string>()
{
{"IntermediateOutputPath", tempPath},
{"ProviderCommandLineArgs", "true"},
{"GenerateResourceMSBuildArchitecture", "CurrentArchitecture"},
{"DesignTimeBuild", "true"},
{"BuildProjectReferences","false"},
{"SkipCompilerExecution","true"},
{"DisableRarCache", "true"},
{"AutoGenerateBindingRedirects", "false"},
{"CopyBuildOutputToOutputDirectory", "false"},
{"CopyOutputSymbolsToOutputDirectory", "false"},
{"SkipCopyBuildProduct", "true"},
{"AddModules", "false"},
{"UseCommonOutputDirectory", "true"},
{"GeneratePackageOnBuild", "false"},
{"RunPostBuildEvent", "false"},
{"SolutionDir", new FileInfo(csprojPath).FullName}
};
var propargs = string.Join(" ", properties.Select(kv => $"/p:{kv.Key}=\"{kv.Value}\""));
// how to determine whether command should be executed('dotnet msbuild' or 'msbuild')?
if (useDotNet)
{
fname = "dotnet";
return (fname, $"msbuild \"{csprojPath}\" /t:{tasks} {propargs} /bl:\"{Path.Combine(tempPath, "build.binlog")}\" /v:n");
}
else
{
fname = "msbuild";
return (fname, $"\"{csprojPath}\" /t:{tasks} {propargs} /bl:\"{Path.Combine(tempPath, "build.binlog")}\" /v:n");
}
}
static async Task<bool> TryExecute(string csprojPath, string tempPath, bool useDotNet)
{
// executing build command with output binary log
var (fname, args) = GetBuildCommandLine(csprojPath, tempPath, useDotNet);
try
{
using (var stdout = new MemoryStream())
using (var stderr = new MemoryStream())
{
var exitCode = await ProcessUtil.ExecuteProcessAsync(fname, args, stdout, stderr, null).ConfigureAwait(false);
if (exitCode == 0)
{
return true;
}
else
{
// write process output to stdout and stderr when error.
using (var stdout2 = new MemoryStream(stdout.ToArray()))
using (var stderr2 = new MemoryStream(stderr.ToArray()))
using (var consoleStdout = Console.OpenStandardOutput())
using (var consoleStderr = Console.OpenStandardError())
{
await stdout2.CopyToAsync(consoleStdout).ConfigureAwait(false);
await stderr2.CopyToAsync(consoleStderr).ConfigureAwait(false);
}
return false;
}
}
}
catch (Exception e)
{
Console.WriteLine($"exception occured(fname={fname}, args={args}):{e}");
return false;
}
}
static async Task<AnalyzerResult[]> GetAnalyzerResults(AnalyzerManager analyzerManager, string csprojPath, params string[] preprocessorSymbols)
{
var tempPath = Path.Combine(new FileInfo(csprojPath).Directory.FullName, "__buildtemp");
try
{
if (!await TryExecute(csprojPath, tempPath, true).ConfigureAwait(false))
{
Console.WriteLine("execute `dotnet msbuild` failed, retry with `msbuild`");
if (!await TryExecute(csprojPath, tempPath, false).ConfigureAwait(false))
{
throw new Exception("failed to build project");
}
}
// get results of analysis from binarylog
return analyzerManager.Analyze(Path.Combine(tempPath, "build.binlog")).ToArray();
}
finally
{
if (Directory.Exists(tempPath))
{
Directory.Delete(tempPath, true);
}
}
}
public static async Task<Compilation> GetCompilationFromProject(string csprojPath, params string[] preprocessorSymbols)
{
var analyzerOptions = new AnalyzerManagerOptions();
@ -26,7 +123,7 @@ namespace MessagePack.CodeGenerator
var projectAnalyzer = manager.GetProject(csprojPath); // addproj
// projectAnalyzer.AddBuildLogger(new Microsoft.Build.Logging.ConsoleLogger(Microsoft.Build.Framework.LoggerVerbosity.Minimal));
var workspace = manager.GetWorkspaceWithPreventBuildEvent();
var workspace = await manager.GetWorkspaceWithPreventBuildEventAsync().ConfigureAwait(false);
workspace.WorkspaceFailed += WorkSpaceFailed;
var project = workspace.CurrentSolution.Projects.First();
@ -43,36 +140,20 @@ namespace MessagePack.CodeGenerator
Console.WriteLine(e);
}
public static AdhocWorkspace GetWorkspaceWithPreventBuildEvent(this AnalyzerManager manager)
// WIP function for getting Roslyn's workspace from csproj
public static async Task<AdhocWorkspace> GetWorkspaceWithPreventBuildEventAsync(this AnalyzerManager manager)
{
// info article: https://qiita.com/skitoy4321/items/9edfb094549f5167a57f
var projPath = manager.Projects.First().Value.ProjectFile.Path;
var tempPath = Path.Combine(new FileInfo(projPath).Directory.FullName, "__buildtemp") + System.IO.Path.DirectorySeparatorChar;
var envopts = new EnvironmentOptions();
// "Clean" and "Build" is listed in default
// Modify to designtime system https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md#targets-that-run-during-design-time-builds
// that prevent Pre/PostBuildEvent
envopts.TargetsToBuild.Clear();
// Clean should not use(if use pre/post build, dll was deleted).
// envopts.TargetsToBuild.Add("Clean");
envopts.TargetsToBuild.Add("ResolveAssemblyReferencesDesignTime");
envopts.TargetsToBuild.Add("ResolveProjectReferencesDesignTime");
envopts.TargetsToBuild.Add("ResolveComReferencesDesignTime");
envopts.TargetsToBuild.Add("Compile");
envopts.GlobalProperties["IntermediateOutputPath"] = tempPath;
try
var ws = new AdhocWorkspace();
foreach (var result in await GetAnalyzerResults(manager, projPath))
{
return GetWorkspace(manager, envopts);
}
finally
{
if (Directory.Exists(tempPath))
// getting only successful build
if (result.Succeeded)
{
Directory.Delete(tempPath, true);
result.AddToWorkspace(ws);
}
}
return ws;
}
public static AdhocWorkspace GetWorkspace(this AnalyzerManager manager, EnvironmentOptions envOptions)

Просмотреть файл

@ -0,0 +1,363 @@
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MessagePack.AspNetCoreMvcFormatter;
using MessagePack.Resolvers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Newtonsoft.Json;
using Xunit;
namespace MessagePack.Tests.ExtensionTests
{
public class AspNetCoreMvcFormatterTest
{
private const string MsgPackContentType = "application/x-msgpack";
private MessagePackSerializer serializer = new MessagePackSerializer();
private LZ4MessagePackSerializer lz4Serializer = new LZ4MessagePackSerializer();
[Fact]
public async Task MessagePackFormatter()
{
var person = new User
{
UserId = 1,
FullName = "John Denver",
Age = 35,
Description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
};
var messagePackBinary = this.serializer.Serialize(person);
// OutputFormatter
var outputFormatterContext = GetOutputFormatterContext(person, typeof(User), MsgPackContentType);
var outputFormatter = new MessagePackOutputFormatter(StandardResolver.Instance);
outputFormatter.CanWriteResult(outputFormatterContext).IsTrue();
await outputFormatter.WriteAsync(outputFormatterContext);
var body = outputFormatterContext.HttpContext.Response.Body;
Assert.NotNull(body);
body.Position = 0;
using (var ms = new MemoryStream())
{
body.CopyTo(ms);
Assert.Equal(messagePackBinary, ms.ToArray());
}
// InputFormatter
var httpContext = new DefaultHttpContext();
httpContext.Features.Set<IHttpResponseFeature>(new TestResponseFeature());
httpContext.Request.Body = new NonSeekableReadStream(messagePackBinary);
httpContext.Request.ContentType = MsgPackContentType;
var inputFormatterContext = CreateInputFormatterContext(typeof(User), httpContext);
var inputFormatter = new MessagePackInputFormatter();
inputFormatter.CanRead(inputFormatterContext).IsTrue();
var result = await inputFormatter.ReadAsync(inputFormatterContext);
Assert.False(result.HasError);
var userModel = Assert.IsType<User>(result.Model);
userModel.IsStructuralEqual(person);
}
[Fact]
public void MessagePackFormatterCanNotRead()
{
var person = new User();
// OutputFormatter
var outputFormatterContext = GetOutputFormatterContext(person, typeof(User), "application/json");
var outputFormatter = new MessagePackOutputFormatter(StandardResolver.Instance);
outputFormatter.CanWriteResult(outputFormatterContext).IsFalse();
// InputFormatter
var httpContext = new DefaultHttpContext();
httpContext.Features.Set<IHttpResponseFeature>(new TestResponseFeature());
httpContext.Request.Body = new NonSeekableReadStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(person)));
httpContext.Request.ContentType = "application/json";
var inputFormatterContext = CreateInputFormatterContext(typeof(User), httpContext);
var inputFormatter = new MessagePackInputFormatter();
inputFormatter.CanRead(inputFormatterContext).IsFalse();
}
[Fact]
public async Task LZ4MessagePackFormatter()
{
var person = new User
{
UserId = 1,
FullName = "John Denver",
Age = 35,
Description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
};
var messagePackBinary = this.serializer.Serialize(person);
var lz4MessagePackBinary = this.lz4Serializer.Serialize(person);
// OutputFormatter
var outputFormatterContext = GetOutputFormatterContext(person, typeof(User), MsgPackContentType);
var outputFormatter = new LZ4MessagePackOutputFormatter(StandardResolver.Instance);
await outputFormatter.WriteAsync(outputFormatterContext);
var body = outputFormatterContext.HttpContext.Response.Body;
Assert.NotNull(body);
body.Position = 0;
using (var ms = new MemoryStream())
{
body.CopyTo(ms);
var binary = ms.ToArray();
binary.IsNot(messagePackBinary);
binary.Is(lz4MessagePackBinary);
}
// InputFormatter
var httpContext = new DefaultHttpContext();
httpContext.Features.Set<IHttpResponseFeature>(new TestResponseFeature());
httpContext.Request.Body = new NonSeekableReadStream(messagePackBinary);
httpContext.Request.ContentType = MsgPackContentType;
var inputFormatterContext = CreateInputFormatterContext(typeof(User), httpContext);
var inputFormatter = new LZ4MessagePackInputFormatter();
var result = await inputFormatter.ReadAsync(inputFormatterContext);
Assert.False(result.HasError);
var userModel = Assert.IsType<User>(result.Model);
userModel.IsStructuralEqual(person);
}
[Fact]
public void LZ4MessagePackFormatterCanNotRead()
{
var person = new User();
// OutputFormatter
var outputFormatterContext = GetOutputFormatterContext(person, typeof(User), "application/json");
var outputFormatter = new LZ4MessagePackOutputFormatter(StandardResolver.Instance);
outputFormatter.CanWriteResult(outputFormatterContext).IsFalse();
// InputFormatter
var httpContext = new DefaultHttpContext();
httpContext.Features.Set<IHttpResponseFeature>(new TestResponseFeature());
httpContext.Request.Body = new NonSeekableReadStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(person)));
httpContext.Request.ContentType = "application/json";
var inputFormatterContext = CreateInputFormatterContext(typeof(User), httpContext);
var inputFormatter = new LZ4MessagePackInputFormatter();
inputFormatter.CanRead(inputFormatterContext).IsFalse();
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs#L453">JsonOutputFormatterTests.cs#L453</see>
/// </summary>
private static OutputFormatterWriteContext GetOutputFormatterContext(
object outputValue,
Type outputType,
string contentType = "application/xml; charset=utf-8",
MemoryStream responseStream = null)
{
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
var actionContext = GetActionContext(mediaTypeHeaderValue, responseStream);
return new OutputFormatterWriteContext(
actionContext.HttpContext,
new TestHttpResponseStreamWriterFactory().CreateWriter,
outputType,
outputValue)
{
ContentType = new StringSegment(contentType),
};
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs#L472">JsonOutputFormatterTests.cs#L472</see>
/// </summary>
private static ActionContext GetActionContext(
MediaTypeHeaderValue contentType,
MemoryStream responseStream = null)
{
var request = new Mock<HttpRequest>();
var headers = new HeaderDictionary();
request.Setup(r => r.ContentType).Returns(contentType.ToString());
request.SetupGet(r => r.Headers).Returns(headers);
headers[HeaderNames.AcceptCharset] = contentType.Charset.ToString();
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(responseStream ?? new MemoryStream());
var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.Request).Returns(request.Object);
httpContext.SetupGet(c => c.Response).Returns(response.Object);
return new ActionContext(httpContext.Object, new RouteData(), new ActionDescriptor());
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs#L717">JsonInputFormatterTest.cs#L717</see>
/// </summary>
private InputFormatterContext CreateInputFormatterContext(
Type modelType,
HttpContext httpContext,
string modelName = null,
bool treatEmptyInputAsDefaultValue = false)
{
var provider = new EmptyModelMetadataProvider();
var metadata = provider.GetMetadataForType(modelType);
return new InputFormatterContext(
httpContext,
modelName: modelName ?? string.Empty,
modelState: new ModelStateDictionary(),
metadata: metadata,
readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader,
treatEmptyInputAsDefaultValue: treatEmptyInputAsDefaultValue);
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs#L791">JsonInputFormatterTest.cs#L791</see>
/// </summary>
private class TestResponseFeature : HttpResponseFeature
{
public override void OnCompleted(Func<object, Task> callback, object state)
{
// do not do anything
}
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/TestHttpResponseStreamWriterFactory.cs">TestHttpResponseStreamWriterFactory.cs</see>
/// </summary>
private class TestHttpResponseStreamWriterFactory : IHttpResponseStreamWriterFactory
{
private const int DefaultBufferSize = 16 * 1024;
public TextWriter CreateWriter(Stream stream, Encoding encoding)
{
return new HttpResponseStreamWriter(stream, encoding, DefaultBufferSize);
}
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/TestHttpRequestStreamReaderFactory.cs">TestHttpRequestStreamReaderFactory.cs</see>
/// </summary>
private class TestHttpRequestStreamReaderFactory : IHttpRequestStreamReaderFactory
{
public TextReader CreateReader(Stream stream, Encoding encoding)
{
return new HttpRequestStreamReader(stream, encoding);
}
}
/// <summary>
/// <see href="https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/NonSeekableReadableStream.cs">NonSeekableReadableStream.cs</see>
/// </summary>
private class NonSeekableReadStream : Stream
{
private Stream _inner;
public NonSeekableReadStream(byte[] data)
: this(new MemoryStream(data))
{
}
public NonSeekableReadStream(Stream inner)
{
_inner = inner;
}
public override bool CanRead => _inner.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length
{
get { throw new NotSupportedException(); }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
count = Math.Max(count, 1);
return _inner.Read(buffer, offset, count);
}
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
count = Math.Max(count, 1);
return _inner.ReadAsync(buffer, offset, count, cancellationToken);
}
}
}
[MessagePackObject]
public class User
{
[Key(0)]
public int UserId { get; set; }
[Key(1)]
public string FullName { get; set; }
[Key(2)]
public int Age { get; set; }
[Key(3)]
public string Description { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Moq" Version="4.10.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MessagePack.AspNetCoreMvcFormatter\MessagePack.AspNetCoreMvcFormatter.csproj" />
<ProjectReference Include="..\..\src\MessagePack\MessagePack.csproj" />
<ProjectReference Include="..\MessagePack.Tests\MessagePack.Tests.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -23,7 +23,7 @@
<PackageReference Include="System.Collections.Immutable" version="1.3.1" />
<PackageReference Include="xunit" version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<PrivateAssets>none</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />