зеркало из https://github.com/Azure/TypeEdge.git
c# contract generation
This commit is contained in:
Родитель
5a75604987
Коммит
623585192f
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"TemperatureSensor": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "metadata=true"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,8 @@ namespace ThermostatApplication
|
|||
//register the modules
|
||||
host.RegisterModule<ITemperatureSensor, TemperatureSensor>();
|
||||
|
||||
//var description = ServiceDescriptor.Describe<TemperatureSensor>(e => JsonSchema4.FromTypeAsync(e).Result.ToJson());
|
||||
//var description = Microsoft.Azure.TypeEdge.Description.ServiceDescriptor.Describe<TemperatureSensor>();
|
||||
//Microsoft.Azure.TypeEdge.Host.Service.ServiceGenerator.CreateFiles(description);
|
||||
|
||||
//host.RegisterExternalModule(new TypeEdge.Host.Docker.DockerModule("tempSensor",
|
||||
// new HostingSettings("mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0", null),
|
||||
|
|
|
@ -111,10 +111,12 @@ namespace Microsoft.Azure.TypeEdge.Host.Docker
|
|||
try
|
||||
{
|
||||
var containers =
|
||||
await _dockerClient.Containers.ListContainersAsync(new ContainersListParameters {All = true}, cancellationToken);
|
||||
await _dockerClient.Containers.ListContainersAsync(new ContainersListParameters {All = true},
|
||||
cancellationToken);
|
||||
if (containers
|
||||
.SingleOrDefault(e => e.Image == (_moduleWithIdentity.Module as Devices.Edge.Agent.Docker.DockerModule)?.Config
|
||||
.Image) != null)
|
||||
.SingleOrDefault(e =>
|
||||
e.Image == (_moduleWithIdentity.Module as Devices.Edge.Agent.Docker.DockerModule)?.Config
|
||||
.Image) != null)
|
||||
{
|
||||
Console.WriteLine($"Removing {_moduleWithIdentity.Module.Name}...");
|
||||
await (await _dockerFactory.RemoveAsync(_moduleWithIdentity.Module))
|
||||
|
|
|
@ -42,6 +42,38 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Docker.DotNet" Version="3.125.2" />
|
||||
<PackageReference Include="NJsonSchema" Version="9.11.0" />
|
||||
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.10" />
|
||||
<PackageReference Include="System.CodeDom" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib">
|
||||
<HintPath>mscorlib</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<HintPath>System</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core">
|
||||
<HintPath>System.Core</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Service\Service.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Service.tt</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Service\Service.tt">
|
||||
<Generator>TextTemplatingFilePreprocessor</Generator>
|
||||
<LastGenOutput>Service.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Azure.TypeEdge.Description;
|
||||
using Newtonsoft.Json.Schema;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
//copied from https://gist.github.com/balexandre/e8cd6a965cdc532cb6ae#file-jsonschematopocos-cs
|
||||
|
||||
public class CodeGenerator
|
||||
{
|
||||
private const string Cyrillic = "Cyrillic";
|
||||
private const string Nullable = "?";
|
||||
private const string PocoClassPrefix = "MailChimp_";
|
||||
|
||||
public string Generate(TypeDescription typeDescription)
|
||||
{
|
||||
var schema = JSchema.Parse(typeDescription.Description);
|
||||
var name = typeDescription.Name;
|
||||
if (schema.Type == null)
|
||||
throw new Exception("Schema does not specify a type.");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
switch (schema.Type)
|
||||
{
|
||||
case JSchemaType.Object:
|
||||
sb.Append(ConvertJsonSchemaObjectToPoco(name, schema));
|
||||
break;
|
||||
|
||||
case JSchemaType.Array:
|
||||
foreach (var item in schema.Items.Where(x => x.Type.HasValue && x.Type == JSchemaType.Object))
|
||||
sb.Append(ConvertJsonSchemaObjectToPoco(null, item));
|
||||
break;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private StringBuilder ConvertJsonSchemaObjectToPoco(string classname, JSchema schema)
|
||||
{
|
||||
return ConvertJsonSchemaObjectToPoco(classname, schema, out var newClassName);
|
||||
}
|
||||
|
||||
private StringBuilder ConvertJsonSchemaObjectToPoco(string className, JSchema schema, out string newClassName)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var isEnum = schema.Enum != null && schema.Enum.Any();
|
||||
|
||||
sb.AppendLine(GenerateObjectSummary(schema));
|
||||
sb.AppendFormat("public {0} ", isEnum ? "enum" : "class");
|
||||
|
||||
if (string.IsNullOrEmpty(className)) className = GetClassName(schema);
|
||||
newClassName = className;
|
||||
|
||||
sb.Append(className);
|
||||
sb.AppendLine(" {");
|
||||
|
||||
if (isEnum)
|
||||
sb.AppendLine(string.Join(",", schema.Enum));
|
||||
else
|
||||
foreach (var item in schema.Properties)
|
||||
{
|
||||
// Property Summary
|
||||
sb.AppendLine(GenerateObjectSummary(item.Value));
|
||||
|
||||
sb.Append("public ");
|
||||
sb.Append(GetClrType(item.Value, sb));
|
||||
sb.Append(" ");
|
||||
sb.Append(item.Key.Trim());
|
||||
sb.AppendLine(" { get; set; }");
|
||||
}
|
||||
|
||||
sb.AppendLine("}");
|
||||
return sb;
|
||||
}
|
||||
|
||||
private string GenerateObjectSummary(JSchema schema)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
// summary
|
||||
sb.AppendLine("\n/// <summary>");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(schema.Title))
|
||||
sb.AppendFormat("/// {0}\n", schema.Title);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(schema.Description))
|
||||
sb.AppendFormat("/// {0}\n", schema.Description);
|
||||
|
||||
sb.AppendLine("/// </summary>");
|
||||
|
||||
// extra data
|
||||
foreach (var ed in schema.ExtensionData) sb.AppendFormat("/// <{0}>{1}</{0}>\n", ed.Key, ed.Value);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private string GetClassName(JSchema schema)
|
||||
{
|
||||
if (schema.Title != null)
|
||||
return string.Format("{0}{1}", PocoClassPrefix, GenerateSlug(schema.Title));
|
||||
return string.Format("{0}{1}", PocoClassPrefix, Guid.NewGuid().ToString("N"));
|
||||
}
|
||||
|
||||
private string GenerateSlug(string phrase)
|
||||
{
|
||||
var str = RemoveAccent(phrase);
|
||||
str = Regex.Replace(str, @"[^a-zA-Z\s-]", ""); // invalid chars
|
||||
str = Regex.Replace(str, @"\s+", " ").Trim(); // convert multiple spaces into one space, trim
|
||||
str = Regex.Replace(str, @"\s", "_"); // convert spaces to underscores
|
||||
return str;
|
||||
}
|
||||
|
||||
private string RemoveAccent(string txt)
|
||||
{
|
||||
var bytes = Encoding.GetEncoding(Cyrillic).GetBytes(txt);
|
||||
return Encoding.ASCII.GetString(bytes);
|
||||
}
|
||||
|
||||
private string GetClrType(JSchema jsonSchema, StringBuilder sb)
|
||||
{
|
||||
string className = null;
|
||||
switch (jsonSchema.Type)
|
||||
{
|
||||
case JSchemaType.Array:
|
||||
if (jsonSchema.Items.Count == 0)
|
||||
return "IEnumerable<object>";
|
||||
if (jsonSchema.Items.Count == 1)
|
||||
return string.Format("IEnumerable<{0}>", GetClrType(jsonSchema.Items.First(), sb));
|
||||
throw new Exception("Not sure what type this will be.");
|
||||
|
||||
case JSchemaType.Boolean:
|
||||
return string.Format("bool{0}",
|
||||
jsonSchema.Required == null || !jsonSchema.Required.Any() ? string.Empty : Nullable);
|
||||
|
||||
case JSchemaType.Number:
|
||||
return string.Format("float{0}",
|
||||
jsonSchema.Required == null || !jsonSchema.Required.Any() ? string.Empty : Nullable);
|
||||
|
||||
case JSchemaType.Integer:
|
||||
return string.Format("int{0}",
|
||||
jsonSchema.Required == null || !jsonSchema.Required.Any() ? string.Empty : Nullable);
|
||||
|
||||
case JSchemaType.String:
|
||||
if (jsonSchema.Enum != null && jsonSchema.Enum.Any())
|
||||
{
|
||||
// it's an enumeration
|
||||
sb.Insert(0, ConvertJsonSchemaObjectToPoco(null, jsonSchema, out className));
|
||||
return className;
|
||||
}
|
||||
|
||||
return "string";
|
||||
|
||||
case JSchemaType.Object:
|
||||
sb.Insert(0, ConvertJsonSchemaObjectToPoco(null, jsonSchema, out className));
|
||||
return className;
|
||||
|
||||
case JSchemaType.None:
|
||||
case JSchemaType.Null:
|
||||
default:
|
||||
return "object";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To be used when $ref has URL's instead Id's
|
||||
public class UrlResolver : JSchemaResolver
|
||||
{
|
||||
public override Stream GetSchemaResource(ResolveSchemaContext context, SchemaReference reference)
|
||||
{
|
||||
return GetStreamFromUrl(reference.BaseUri);
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/a/19051936/28004
|
||||
private Stream GetStreamFromUrl(Uri url)
|
||||
{
|
||||
byte[] refData = null;
|
||||
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
refData = wc.DownloadData(url);
|
||||
}
|
||||
|
||||
return new MemoryStream(refData);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
public class CodeGeneratorSettings
|
||||
{
|
||||
public static CodeGeneratorSettings Default { get; } = new CodeGeneratorSettings
|
||||
{Namespace = "TypeEdge.Proxy", OutputPath = "./TypeEdge.Proxy"};
|
||||
|
||||
public string Namespace { get; set; }
|
||||
public string OutputPath { get; set; }
|
||||
public Language Language { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
public enum Language
|
||||
{
|
||||
CSharp = 0,
|
||||
TypeScript = 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,435 @@
|
|||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 15.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
#line 1 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
[GeneratedCode("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
|
||||
public partial class Service : ServiceBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public virtual string TransformText()
|
||||
{
|
||||
Write("\r\nusing Microsoft.Azure.TypeEdge.Attributes;\r\nusing Microsoft.Azure.TypeEdge.Modu" +
|
||||
"les.Endpoints;\r\nusing Microsoft.Azure.TypeEdge.Twins;\r\n \r\nnamespace ");
|
||||
|
||||
#line 11 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(_codeGeneratorSettings.Namespace));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("\r\n{\r\n [TypeModule]\r\n public interface I");
|
||||
|
||||
#line 14 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(_serviceDescription.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" \r\n {\r\n ");
|
||||
|
||||
#line 16 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
if (_serviceDescription.InputDescriptions != null)
|
||||
foreach (var endpoint in _serviceDescription.InputDescriptions)
|
||||
{
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" Input<");
|
||||
|
||||
#line 20 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(endpoint.TypeDescription.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("> ");
|
||||
|
||||
#line 20 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(endpoint.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" { get; set; }\r\n\t");
|
||||
|
||||
#line 21 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("\r\n\t");
|
||||
|
||||
#line 25 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
if (_serviceDescription.OutputDescriptions != null)
|
||||
foreach (var endpoint in _serviceDescription.OutputDescriptions)
|
||||
{
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" Output<");
|
||||
|
||||
#line 29 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(endpoint.TypeDescription.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("> ");
|
||||
|
||||
#line 29 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(endpoint.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" { get; set; }\r\n\t");
|
||||
|
||||
#line 30 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("\r\n\t");
|
||||
|
||||
#line 34 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
if (_serviceDescription.TwinDescriptions != null)
|
||||
foreach (var twin in _serviceDescription.TwinDescriptions)
|
||||
{
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" ModuleTwin<");
|
||||
|
||||
#line 38 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(twin.TypeDescription.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("> ");
|
||||
|
||||
#line 38 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(twin.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" { get; set; }\r\n\t");
|
||||
|
||||
#line 39 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("\r\n\r\n\t");
|
||||
|
||||
#line 44 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
if (_serviceDescription.DirectMethodDescriptions != null)
|
||||
foreach (var method in _serviceDescription.DirectMethodDescriptions)
|
||||
{
|
||||
var returnType = "void";
|
||||
var arguments = "";
|
||||
if (method.ReturnTypeDescription != null)
|
||||
returnType = method.ReturnTypeDescription.Name;
|
||||
if (method.ArgumentsTypeDescription != null)
|
||||
arguments = string.Join(",",
|
||||
method.ArgumentsTypeDescription.Select(e => $"{e.TypeDescription.Name} {e.Name}")
|
||||
.ToArray());
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" ");
|
||||
|
||||
#line 54 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(returnType));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(" ");
|
||||
|
||||
#line 54 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(method.Name));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("(");
|
||||
|
||||
#line 54 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
Write(ToStringHelper.ToStringWithCulture(arguments));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write(");\r\n\t");
|
||||
|
||||
#line 55 "C:\work\oss\me\TypeEdge\Microsoft.Azure.TypeEdge.Host\Service\Service.tt"
|
||||
}
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Write("\r\n }\r\n}");
|
||||
return GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#region Base class
|
||||
|
||||
/// <summary>
|
||||
/// Base class for this transformation
|
||||
/// </summary>
|
||||
[GeneratedCode("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
|
||||
public class ServiceBase
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private StringBuilder generationEnvironmentField;
|
||||
private CompilerErrorCollection errorsField;
|
||||
private List<int> indentLengthsField;
|
||||
private bool endsWithNewline;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// The string builder that generation-time code is using to assemble generated output
|
||||
/// </summary>
|
||||
protected StringBuilder GenerationEnvironment
|
||||
{
|
||||
get
|
||||
{
|
||||
if (generationEnvironmentField == null) generationEnvironmentField = new StringBuilder();
|
||||
return generationEnvironmentField;
|
||||
}
|
||||
set => generationEnvironmentField = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The error collection for the generation process
|
||||
/// </summary>
|
||||
public CompilerErrorCollection Errors
|
||||
{
|
||||
get
|
||||
{
|
||||
if (errorsField == null) errorsField = new CompilerErrorCollection();
|
||||
return errorsField;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of the lengths of each indent that was added with PushIndent
|
||||
/// </summary>
|
||||
private List<int> indentLengths
|
||||
{
|
||||
get
|
||||
{
|
||||
if (indentLengthsField == null) indentLengthsField = new List<int>();
|
||||
return indentLengthsField;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current indent we use when adding lines to the output
|
||||
/// </summary>
|
||||
public string CurrentIndent { get; private set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Current transformation session
|
||||
/// </summary>
|
||||
public virtual IDictionary<string, object> Session { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Transform-time helpers
|
||||
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string textToAppend)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textToAppend)) return;
|
||||
// If we're starting off, or if the previous text ended with a newline,
|
||||
// we have to append the current indent first.
|
||||
if (GenerationEnvironment.Length == 0
|
||||
|| endsWithNewline)
|
||||
{
|
||||
GenerationEnvironment.Append(CurrentIndent);
|
||||
endsWithNewline = false;
|
||||
}
|
||||
|
||||
// Check if the current text ends with a newline
|
||||
if (textToAppend.EndsWith(Environment.NewLine, StringComparison.CurrentCulture)) endsWithNewline = true;
|
||||
// This is an optimization. If the current indent is "", then we don't have to do any
|
||||
// of the more complex stuff further down.
|
||||
if (CurrentIndent.Length == 0)
|
||||
{
|
||||
GenerationEnvironment.Append(textToAppend);
|
||||
return;
|
||||
}
|
||||
|
||||
// Everywhere there is a newline in the text, add an indent after it
|
||||
textToAppend = textToAppend.Replace(Environment.NewLine, Environment.NewLine + CurrentIndent);
|
||||
// If the text ends with a newline, then we should strip off the indent added at the very end
|
||||
// because the appropriate indent will be added when the next time Write() is called
|
||||
if (endsWithNewline)
|
||||
GenerationEnvironment.Append(textToAppend, 0, textToAppend.Length - CurrentIndent.Length);
|
||||
else
|
||||
GenerationEnvironment.Append(textToAppend);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string textToAppend)
|
||||
{
|
||||
Write(textToAppend);
|
||||
GenerationEnvironment.AppendLine();
|
||||
endsWithNewline = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string format, params object[] args)
|
||||
{
|
||||
Write(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string format, params object[] args)
|
||||
{
|
||||
WriteLine(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise an error
|
||||
/// </summary>
|
||||
public void Error(string message)
|
||||
{
|
||||
var error = new CompilerError();
|
||||
error.ErrorText = message;
|
||||
Errors.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise a warning
|
||||
/// </summary>
|
||||
public void Warning(string message)
|
||||
{
|
||||
var error = new CompilerError();
|
||||
error.ErrorText = message;
|
||||
error.IsWarning = true;
|
||||
Errors.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase the indent
|
||||
/// </summary>
|
||||
public void PushIndent(string indent)
|
||||
{
|
||||
if (indent == null) throw new ArgumentNullException("indent");
|
||||
CurrentIndent = CurrentIndent + indent;
|
||||
indentLengths.Add(indent.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the last indent that was added with PushIndent
|
||||
/// </summary>
|
||||
public string PopIndent()
|
||||
{
|
||||
var returnValue = "";
|
||||
if (indentLengths.Count > 0)
|
||||
{
|
||||
var indentLength = indentLengths[indentLengths.Count - 1];
|
||||
indentLengths.RemoveAt(indentLengths.Count - 1);
|
||||
if (indentLength > 0)
|
||||
{
|
||||
returnValue = CurrentIndent.Substring(CurrentIndent.Length - indentLength);
|
||||
CurrentIndent = CurrentIndent.Remove(CurrentIndent.Length - indentLength);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove any indentation
|
||||
/// </summary>
|
||||
public void ClearIndent()
|
||||
{
|
||||
indentLengths.Clear();
|
||||
CurrentIndent = "";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToString Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Utility class to produce culture-oriented representation of an object as a string.
|
||||
/// </summary>
|
||||
public class ToStringInstanceHelper
|
||||
{
|
||||
private IFormatProvider formatProviderField = CultureInfo.InvariantCulture;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets format provider to be used by ToStringWithCulture method.
|
||||
/// </summary>
|
||||
public IFormatProvider FormatProvider
|
||||
{
|
||||
get => formatProviderField;
|
||||
set
|
||||
{
|
||||
if (value != null) formatProviderField = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
|
||||
/// </summary>
|
||||
public string ToStringWithCulture(object objectToConvert)
|
||||
{
|
||||
if (objectToConvert == null) throw new ArgumentNullException("objectToConvert");
|
||||
var t = objectToConvert.GetType();
|
||||
var method = t.GetMethod("ToString", new[]
|
||||
{
|
||||
typeof(IFormatProvider)
|
||||
});
|
||||
if (method == null)
|
||||
return objectToConvert.ToString();
|
||||
return (string) method.Invoke(objectToConvert, new object[]
|
||||
{
|
||||
formatProviderField
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to produce culture-oriented representation of an object as a string
|
||||
/// </summary>
|
||||
public ToStringInstanceHelper ToStringHelper { get; } = new ToStringInstanceHelper();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.Azure.TypeEdge.Description;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
partial class Service
|
||||
{
|
||||
private readonly CodeGeneratorSettings _codeGeneratorSettings;
|
||||
private readonly ServiceDescription _serviceDescription;
|
||||
|
||||
public Service(ServiceDescription serviceDescription, CodeGeneratorSettings codeGeneratorSettings)
|
||||
{
|
||||
_serviceDescription = serviceDescription;
|
||||
_codeGeneratorSettings = codeGeneratorSettings;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<#@ template language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
|
||||
using Microsoft.Azure.TypeEdge.Attributes;
|
||||
using Microsoft.Azure.TypeEdge.Modules.Endpoints;
|
||||
using Microsoft.Azure.TypeEdge.Twins;
|
||||
|
||||
namespace <#= _codeGeneratorSettings.Namespace #>
|
||||
{
|
||||
[TypeModule]
|
||||
public interface I<#= _serviceDescription.Name #>
|
||||
{
|
||||
<# if(_serviceDescription.InputDescriptions!=null)
|
||||
foreach (var endpoint in _serviceDescription.InputDescriptions)
|
||||
{
|
||||
#>
|
||||
Input<<#= endpoint.TypeDescription.Name #>> <#= endpoint.Name #> { get; set; }
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
||||
<# if(_serviceDescription.OutputDescriptions!=null)
|
||||
foreach (var endpoint in _serviceDescription.OutputDescriptions)
|
||||
{
|
||||
#>
|
||||
Output<<#= endpoint.TypeDescription.Name #>> <#= endpoint.Name #> { get; set; }
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
||||
<# if(_serviceDescription.TwinDescriptions!=null)
|
||||
foreach (var twin in _serviceDescription.TwinDescriptions)
|
||||
{
|
||||
#>
|
||||
ModuleTwin<<#= twin.TypeDescription.Name #>> <#= twin.Name #> { get; set; }
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
||||
|
||||
<# if(_serviceDescription.DirectMethodDescriptions!=null)
|
||||
foreach (var method in _serviceDescription.DirectMethodDescriptions)
|
||||
{
|
||||
string returnType = "void";
|
||||
string arguments = "";
|
||||
if(method.ReturnTypeDescription!=null)
|
||||
returnType = method.ReturnTypeDescription.Name;
|
||||
if(method.ArgumentsTypeDescription!=null)
|
||||
arguments = string.Join( ",", method.ArgumentsTypeDescription.Select(e => $"{e.TypeDescription.Name} {e.Name}").ToArray());
|
||||
#>
|
||||
<#= returnType #> <#= method.Name #>(<#= arguments #>);
|
||||
<#
|
||||
}
|
||||
#>
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Azure.TypeEdge.Description;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Host.Service
|
||||
{
|
||||
public class ServiceGenerator
|
||||
{
|
||||
public static bool CreateFiles(ServiceDescription service)
|
||||
{
|
||||
return CreateFiles(service, new CodeGenerator().Generate);
|
||||
}
|
||||
|
||||
public static bool CreateFiles(ServiceDescription service, Func<TypeDescription, string> codeGenerator)
|
||||
{
|
||||
var settings = CodeGeneratorSettings.Default;
|
||||
settings.Namespace = service.Name + ".Proxy";
|
||||
settings.OutputPath = "./" + settings.Namespace;
|
||||
|
||||
return CreateFiles(service, codeGenerator, settings);
|
||||
}
|
||||
|
||||
public static bool CreateFiles(ServiceDescription serviceDescription,
|
||||
Func<TypeDescription, string> codeGenerator,
|
||||
CodeGeneratorSettings settings)
|
||||
{
|
||||
var service = new Service(serviceDescription, settings);
|
||||
var serviceCode = service.TransformText();
|
||||
|
||||
|
||||
if (!Directory.Exists(settings.OutputPath))
|
||||
Directory.CreateDirectory(settings.OutputPath);
|
||||
|
||||
|
||||
foreach (var endpoint in serviceDescription.InputDescriptions)
|
||||
{
|
||||
var code = codeGenerator(endpoint.TypeDescription);
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, endpoint.TypeDescription.Name + ".cs"), code);
|
||||
}
|
||||
|
||||
foreach (var endpoint in serviceDescription.OutputDescriptions)
|
||||
{
|
||||
var code = codeGenerator(endpoint.TypeDescription);
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, endpoint.TypeDescription.Name + ".cs"), code);
|
||||
}
|
||||
|
||||
foreach (var twin in serviceDescription.TwinDescriptions)
|
||||
{
|
||||
var code = codeGenerator(twin.TypeDescription);
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, twin.TypeDescription.Name + ".cs"), code);
|
||||
}
|
||||
|
||||
foreach (var method in serviceDescription.DirectMethodDescriptions)
|
||||
{
|
||||
if (method.ReturnTypeDescription != null)
|
||||
{
|
||||
var code = codeGenerator(method.ReturnTypeDescription);
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, method.ReturnTypeDescription.Name + ".cs"),
|
||||
code);
|
||||
}
|
||||
|
||||
if (method.ArgumentsTypeDescription != null)
|
||||
foreach (var arg in method.ArgumentsTypeDescription)
|
||||
{
|
||||
var code = codeGenerator(arg.TypeDescription);
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, arg.TypeDescription.Name + ".cs"),
|
||||
code);
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(Path.Combine(settings.OutputPath, $"I{serviceDescription.Name}.cs"), serviceCode);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -53,6 +53,7 @@ namespace Microsoft.Azure.TypeEdge.Host
|
|||
_deviceId = configuration.GetValue<string>("DeviceId");
|
||||
_iotHubConnectionString = configuration.GetValue<string>("IotHubConnectionString");
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(_iotHubConnectionString))
|
||||
throw new Exception("Missing \"IotHubConnectionString\" value in configuration");
|
||||
|
||||
|
@ -449,7 +450,7 @@ namespace Microsoft.Azure.TypeEdge.Host
|
|||
|
||||
var registryManager = RegistryManager.CreateFromConnectionString(_iotHubConnectionString);
|
||||
var device = await registryManager.GetDeviceAsync(_deviceId) ?? await registryManager.AddDeviceAsync(
|
||||
new Device(_deviceId) { Capabilities = new DeviceCapabilities { IotEdge = true } });
|
||||
new Device(_deviceId) {Capabilities = new DeviceCapabilities {IotEdge = true}});
|
||||
var sasKey = device.Authentication.SymmetricKey.PrimaryKey;
|
||||
|
||||
try
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
{
|
||||
public class ArgumentDescription
|
||||
{
|
||||
public ArgumentDescription(string argumentName, Type type, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
Name = argumentName;
|
||||
TypeDescription = new TypeDescription(type, schemaGenerator);
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public TypeDescription TypeDescription { get; set; }
|
||||
}
|
||||
}
|
|
@ -6,17 +6,17 @@ namespace Microsoft.Azure.TypeEdge.Description
|
|||
{
|
||||
public class DirectMethodDescription
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string[] ArgumentsTypeDescription { get; set; }
|
||||
public string ReturnTypeDescription { get; set; }
|
||||
|
||||
public DirectMethodDescription(MethodInfo mi, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
|
||||
Name = mi.Name;
|
||||
if (mi.ReturnType != typeof(void))
|
||||
ReturnTypeDescription = schemaGenerator(mi.ReturnType);
|
||||
ArgumentsTypeDescription = mi.GetParameters().Select(p => schemaGenerator(p.ParameterType)).ToArray();
|
||||
ReturnTypeDescription = new TypeDescription(mi.ReturnType, schemaGenerator);
|
||||
ArgumentsTypeDescription = mi.GetParameters()
|
||||
.Select(p => new ArgumentDescription(p.Name, p.ParameterType, schemaGenerator)).ToArray();
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public ArgumentDescription[] ArgumentsTypeDescription { get; set; }
|
||||
public TypeDescription ReturnTypeDescription { get; set; }
|
||||
}
|
||||
}
|
|
@ -4,14 +4,14 @@ namespace Microsoft.Azure.TypeEdge.Description
|
|||
{
|
||||
public class EndpointDescription
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public string TypeDescription { get; }
|
||||
|
||||
public EndpointDescription(string name, Type type, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
Name = name;
|
||||
TypeDescription = schemaGenerator(type);
|
||||
TypeDescription = new TypeDescription(type, schemaGenerator);
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public TypeDescription TypeDescription { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using Newtonsoft.Json.Schema.Generation;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
{
|
||||
public class SchemaGenerator
|
||||
{
|
||||
private readonly JSchemaGenerator JSchemaGenerator;
|
||||
|
||||
public SchemaGenerator()
|
||||
{
|
||||
JSchemaGenerator = new JSchemaGenerator();
|
||||
}
|
||||
|
||||
public string Generate(Type type)
|
||||
{
|
||||
return JSchemaGenerator.Generate(type).ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
{
|
||||
public class ServiceDescription
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public EndpointDescription[] InputDescriptions { get; set; }
|
||||
public EndpointDescription[] OutputDescriptions { get; set; }
|
||||
public TwinDescription TwinDescription { get; set; }
|
||||
public TwinDescription[] TwinDescriptions { get; set; }
|
||||
public DirectMethodDescription[] DirectMethodDescriptions { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,39 +10,63 @@ namespace Microsoft.Azure.TypeEdge.Description
|
|||
{
|
||||
public static class ServiceDescriptor
|
||||
{
|
||||
public static ServiceDescription Describe(Type type)
|
||||
{
|
||||
return Describe(type, new SchemaGenerator().Generate);
|
||||
}
|
||||
|
||||
public static ServiceDescription Describe<T>()
|
||||
where T : TypeModule
|
||||
{
|
||||
return Describe(typeof(T));
|
||||
}
|
||||
|
||||
public static ServiceDescription Describe<T>(Func<Type, string> schemaGenerator)
|
||||
where T : TypeModule
|
||||
where T : TypeModule
|
||||
{
|
||||
return Describe(typeof(T), schemaGenerator);
|
||||
}
|
||||
|
||||
public static ServiceDescription Describe(Type type, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
return new ServiceDescription
|
||||
{
|
||||
InputDescriptions = GetEndpointDescription<T>(typeof(Input<>), schemaGenerator),
|
||||
OutputDescriptions = GetEndpointDescription<T>(typeof(Output<>), schemaGenerator),
|
||||
TwinDescription = GetTwinDescription<T>(typeof(ModuleTwin<>), schemaGenerator),
|
||||
DirectMethodDescriptions = GetDirectMethodDescriptions<T>(schemaGenerator)
|
||||
Name = type.Name,
|
||||
InputDescriptions = GetEndpointDescription(type, typeof(Input<>), schemaGenerator),
|
||||
OutputDescriptions = GetEndpointDescription(type, typeof(Output<>), schemaGenerator),
|
||||
TwinDescriptions = GetTwinDescription(type, typeof(ModuleTwin<>), schemaGenerator),
|
||||
DirectMethodDescriptions = GetDirectMethodDescriptions(type, schemaGenerator)
|
||||
};
|
||||
}
|
||||
|
||||
private static DirectMethodDescription[] GetDirectMethodDescriptions<T>(Func<Type, string> schemaGenerator)
|
||||
private static DirectMethodDescription[] GetDirectMethodDescriptions(Type type,
|
||||
Func<Type, string> schemaGenerator)
|
||||
{
|
||||
return typeof(T).GetProxyInterface().GetMethods().Where(m => !m.IsSpecialName).Select(e => new DirectMethodDescription(e, schemaGenerator)).ToArray();
|
||||
return type.GetProxyInterface().GetMethods().Where(m => !m.IsSpecialName)
|
||||
.Select(e => new DirectMethodDescription(e, schemaGenerator)).ToArray();
|
||||
}
|
||||
|
||||
private static EndpointDescription[] GetEndpointDescription<T>(Type propertyType, Func<Type, string> schemaGenerator)
|
||||
private static EndpointDescription[] GetEndpointDescription(Type type, Type propertyType,
|
||||
Func<Type, string> schemaGenerator)
|
||||
{
|
||||
return GetPropertyInfos<T>(propertyType)
|
||||
.Select(e => new EndpointDescription(e.Name, e.PropertyType.GenericTypeArguments[0], schemaGenerator)).ToArray();
|
||||
return GetPropertyInfos(type, propertyType)
|
||||
.Select(e => new EndpointDescription(e.Name, e.PropertyType.GenericTypeArguments[0], schemaGenerator))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static TwinDescription GetTwinDescription<T>(Type propertyType, Func<Type, string> schemaGenerator)
|
||||
private static TwinDescription[] GetTwinDescription(Type type, Type propertyType,
|
||||
Func<Type, string> schemaGenerator)
|
||||
{
|
||||
return new TwinDescription(GetPropertyInfos<T>(propertyType).Select(e => e.PropertyType.GenericTypeArguments[0]), schemaGenerator);
|
||||
return GetPropertyInfos(type, propertyType)
|
||||
.Select(e => new TwinDescription(e.Name, e.PropertyType.GenericTypeArguments[0], schemaGenerator))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static IEnumerable<PropertyInfo> GetPropertyInfos<T>(Type propertyType)
|
||||
private static IEnumerable<PropertyInfo> GetPropertyInfos(Type type, Type propertyType)
|
||||
{
|
||||
return typeof(T).GetProperties().Where(e =>
|
||||
return type.GetProperties().Where(e =>
|
||||
e.PropertyType.IsGenericType &&
|
||||
e.PropertyType.GetGenericTypeDefinition().IsAssignableFrom(propertyType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
{
|
||||
public class TwinDescription
|
||||
{
|
||||
public string TypeDescription { get; }
|
||||
|
||||
public TwinDescription(IEnumerable<Type> types, Func<Type, string> schemaGenerator)
|
||||
public TwinDescription(string name, Type type, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
if (types == null || !types.Any())
|
||||
return;
|
||||
|
||||
var mergeSettings = new JsonMergeSettings
|
||||
{
|
||||
MergeArrayHandling = MergeArrayHandling.Union
|
||||
};
|
||||
|
||||
var typeJObjects = types.Select(e => JObject.Parse(schemaGenerator(e))).ToArray();
|
||||
var union = typeJObjects[0];
|
||||
for (var i = 0; i < typeJObjects.Length-1; i++)
|
||||
union.Merge(typeJObjects[i + 1], mergeSettings);
|
||||
|
||||
TypeDescription = union.ToString(Formatting.None);
|
||||
|
||||
Name = name;
|
||||
TypeDescription = new TypeDescription(type, schemaGenerator);
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public TypeDescription TypeDescription { get; }
|
||||
|
||||
//public TwinDescription(IEnumerable<Type> types, Func<Type, string> schemaGenerator)
|
||||
//{
|
||||
// if (types == null || !types.Any())
|
||||
// return;
|
||||
|
||||
// var mergeSettings = new JsonMergeSettings
|
||||
// {
|
||||
// MergeArrayHandling = MergeArrayHandling.Union
|
||||
// };
|
||||
|
||||
// var typeJObjects = types.Select(e => JObject.Parse(schemaGenerator(e))).ToArray();
|
||||
// var union = typeJObjects[0];
|
||||
// for (var i = 0; i < typeJObjects.Length-1; i++)
|
||||
// union.Merge(typeJObjects[i + 1], mergeSettings);
|
||||
|
||||
// TypeDescription = union.ToString(Formatting.None);
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge.Description
|
||||
{
|
||||
public class TypeDescription
|
||||
{
|
||||
public TypeDescription(Type type, Func<Type, string> schemaGenerator)
|
||||
{
|
||||
Name = type.Name;
|
||||
Description = schemaGenerator(type);
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
|
@ -33,13 +33,10 @@
|
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.10" />
|
||||
<PackageReference Include="Serilog" Version="2.7.1" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="NewFolder\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace Microsoft.Azure.TypeEdge.Modules.Endpoints
|
|||
_volume.Delete(fileName);
|
||||
|
||||
return res;
|
||||
|
||||
});
|
||||
|
||||
Module.SubscribeRoute(output.Name,
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace Microsoft.Azure.TypeEdge.Modules.Messages
|
|||
{
|
||||
public abstract class EdgeMessage : IEdgeMessage
|
||||
{
|
||||
public IDictionary<string, string> Properties { get; set; }
|
||||
[JsonIgnore] public IDictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
|
|
|
@ -138,7 +138,8 @@ namespace Microsoft.Azure.TypeEdge.Modules
|
|||
Logger.LogWarning($"Missing {Constants.EdgeHubConnectionStringKey} variable.");
|
||||
|
||||
var settings = new AmqpTransportSettings(TransportType.Amqp_Tcp_Only);
|
||||
var disableSslCertificateValidationKey = configuration.GetValue($"{Constants.DisableSslCertificateValidationKey}", false);
|
||||
var disableSslCertificateValidationKey =
|
||||
configuration.GetValue($"{Constants.DisableSslCertificateValidationKey}", false);
|
||||
|
||||
if (disableSslCertificateValidationKey)
|
||||
settings.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
|
@ -211,10 +212,7 @@ namespace Microsoft.Azure.TypeEdge.Modules
|
|||
|
||||
var volumePath = volumeName.ToLower();
|
||||
|
||||
if (!Directory.Exists(volumePath))
|
||||
{
|
||||
Directory.CreateDirectory(volumePath);
|
||||
}
|
||||
if (!Directory.Exists(volumePath)) Directory.CreateDirectory(volumePath);
|
||||
|
||||
Volumes[volumeName] = volumePath;
|
||||
}
|
||||
|
@ -416,6 +414,9 @@ namespace Microsoft.Azure.TypeEdge.Modules
|
|||
|
||||
input.SetBytes(messageBytes);
|
||||
|
||||
foreach (var messageProperty in message.Properties)
|
||||
input.Properties.Add(messageProperty.Key, messageProperty.Value);
|
||||
|
||||
var invocationResult = callback.Handler.DynamicInvoke(input);
|
||||
var result = await (Task<MessageResult>) invocationResult;
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ using Microsoft.Azure.TypeEdge.Proxy;
|
|||
using Microsoft.Azure.TypeEdge.Volumes;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using static System.String;
|
||||
using ServiceDescriptor = Microsoft.Azure.TypeEdge.Description.ServiceDescriptor;
|
||||
|
||||
namespace Microsoft.Azure.TypeEdge
|
||||
{
|
||||
|
@ -43,14 +45,12 @@ namespace Microsoft.Azure.TypeEdge
|
|||
|
||||
if (IsNullOrEmpty(moduleName))
|
||||
{
|
||||
Console.WriteLine($"WARN:No {Constants.ModuleNameConfigName} in configuration. ");
|
||||
|
||||
moduleName = DiscoverModuleName();
|
||||
if (IsNullOrEmpty(moduleName))
|
||||
{
|
||||
Console.WriteLine($"WARN:No {Constants.ModuleNameConfigName} in configuration. ");
|
||||
Console.WriteLine("Exiting...");
|
||||
return;
|
||||
//throw new ArgumentException($"No moduleName in arguments");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,13 @@ namespace Microsoft.Azure.TypeEdge
|
|||
if (moduleType == null)
|
||||
throw new ArgumentException($"No module called {moduleName} in calling assembly");
|
||||
|
||||
if (configuration.GetValue("metadata", false))
|
||||
{
|
||||
var description = ServiceDescriptor.Describe(moduleType);
|
||||
Console.WriteLine(JsonConvert.SerializeObject(description, Formatting.Indented));
|
||||
return;
|
||||
}
|
||||
|
||||
var connectionString = configuration.GetValue<string>($"{Constants.EdgeHubConnectionStringKey}");
|
||||
|
||||
if (IsNullOrEmpty(connectionString))
|
||||
|
@ -105,9 +112,9 @@ namespace Microsoft.Azure.TypeEdge
|
|||
|
||||
var moduleDependencies = moduleType.GetConstructors().First().GetParameters();
|
||||
var moduleDependencyTypes = moduleDependencies.Where(i => i.ParameterType.IsInterface &&
|
||||
i.ParameterType.GetCustomAttribute(
|
||||
typeof(TypeModuleAttribute),
|
||||
true) != null).Select(e => e.ParameterType);
|
||||
i.ParameterType.GetCustomAttribute(
|
||||
typeof(TypeModuleAttribute),
|
||||
true) != null).Select(e => e.ParameterType);
|
||||
|
||||
var proxyGenerator = new ProxyGenerator();
|
||||
foreach (var dependency in moduleDependencyTypes)
|
||||
|
@ -171,6 +178,6 @@ namespace Microsoft.Azure.TypeEdge
|
|||
var moduleInterfaceType = moduleType.GetProxyInterface();
|
||||
moduleTypes = (moduleType, moduleInterfaceType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче