2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-06-13 14:38:43 +00:00

TypeDefGenerator

This commit is contained in:
2026-06-08 23:25:49 +03:00
parent 0939f71464
commit 2bdd5d5022
23 changed files with 348 additions and 43 deletions
@@ -124,6 +124,9 @@ public class RemoteTypeDef:TypeDef
} }
} }
// try to get proxy type
od._proxyType = connection.Instance?.Warehouse?.TryGetProxyType(od.Kind, od.Domain, od.Name);
return od; return od;
} }
} }
+20 -5
View File
@@ -271,9 +271,13 @@ public static class TypeDefGenerator
// generate info class // generate info class
var mainClassName = typeDefs.FirstOrDefault().Name?.Split('.');
var mainNamespace = mainClassName != null ? string.Join(".", mainClassName.Take(mainClassName.Length - 1)) : "Esiur";
var typesFile = @"using System; var typesFile = @"using System;
namespace Esiur { namespace " + mainNamespace + @" {
public static class Generated { public static class Initialization {
public static Type[] Resources {get;} = new Type[] { " + public static Type[] Resources {get;} = new Type[] { " +
string.Join(",", typeDefs.Where(x => x.Kind == TypeDefKind.Resource).Select(x => $"typeof({x.Name})")) string.Join(",", typeDefs.Where(x => x.Kind == TypeDefKind.Resource).Select(x => $"typeof({x.Name})"))
+ @" }; + @" };
@@ -282,11 +286,22 @@ public static class TypeDefGenerator
+ @" }; + @" };
public static Type[] Enums { get; } = new Type[] { " + public static Type[] Enums { get; } = new Type[] { " +
string.Join(",", typeDefs.Where(x => x.Kind == TypeDefKind.Enum).Select(x => $"typeof({x.Name})")) string.Join(",", typeDefs.Where(x => x.Kind == TypeDefKind.Enum).Select(x => $"typeof({x.Name})"))
+ @" };" + + @" };
"\r\n } \r\n}"; public static void RegisterTypes(Warehouse warehouse)
{
foreach(var type in Resources)
warehouse.RegisterProxyType(type);
foreach(var type in Records)
warehouse.RegisterProxyType(type);
foreach(var type in Enums)
warehouse.RegisterProxyType(type);
}
\r\n } \r\n}";
File.WriteAllText(dstDir.FullName + Path.DirectorySeparatorChar + "Esiur.g.cs", typesFile); File.WriteAllText(dstDir.FullName + Path.DirectorySeparatorChar + "Initialization.g.cs", typesFile);
return dstDir.FullName; return dstDir.FullName;
+188 -4
View File
@@ -1,19 +1,203 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
namespace Esiur.Resource namespace Esiur.Resource
{ {
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Class, Inherited = false)] [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Class, Inherited = false)]
public class RemoteAttribute:Attribute public class RemoteAttribute : Attribute
{ {
public string Domain { get; private set; } public string[] Domains { get; private set; }
public string FullName { get; private set; } public string FullName { get; private set; }
public RemoteAttribute(string domain, string fullName) static readonly Regex StrictIPv4 = new(
@"^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
static readonly Regex IPv4Like = new(
@"^\d+(?:\.\d+){3}$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
static readonly Regex HostName = new(
@"^(?=.{1,253}\.?$)(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)*[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.?$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
public bool IsValidFullName()
{ {
Domain = domain; return IsValidQualifiedClassName(FullName, true, false); ;
}
private static readonly HashSet<string> ReservedKeywords = new HashSet<string>(
new[]
{
"abstract", "as", "base", "bool", "break", "byte", "case", "catch",
"char", "checked", "class", "const", "continue", "decimal", "default",
"delegate", "do", "double", "else", "enum", "event", "explicit",
"extern", "false", "finally", "fixed", "float", "for", "foreach",
"goto", "if", "implicit", "in", "int", "interface", "internal",
"is", "lock", "long", "namespace", "new", "null", "object",
"operator", "out", "override", "params", "private", "protected",
"public", "readonly", "ref", "return", "sbyte", "sealed", "short",
"sizeof", "stackalloc", "static", "string", "struct", "switch",
"this", "throw", "true", "try", "typeof", "uint", "ulong",
"unchecked", "unsafe", "ushort", "using", "virtual", "void",
"volatile", "while"
},
StringComparer.Ordinal);
public RemoteAttribute(string fullName, params string[] domains)
{
Domains = domains;
FullName = fullName; FullName = fullName;
} }
// @TODO: support wildcard records
public bool AreValidDomains()
{
foreach(var domain in Domains)
{
if (!IsValidDomain(domain))
return false;
}
return true;
}
private bool IsValidDomain(string domain)
{
if (string.IsNullOrWhiteSpace(domain))
return false;
string s = domain.Trim();
// Accept URI-style IPv6 literals, e.g. [::1]
if (s.Length > 2 && s[0] == '[' && s[s.Length - 1] == ']')
s = s.Substring(1, s.Length - 2);
// Strict IPv4 only: 0.0.0.0 to 255.255.255.255
if (StrictIPv4.IsMatch(s))
return true;
// Reject IPv4-looking strings that failed strict IPv4,
// e.g. 999.999.999.999
if (IPv4Like.IsMatch(s))
return false;
IPAddress ip;
// IPv6
if (IPAddress.TryParse(s, out ip) &&
ip.AddressFamily == AddressFamily.InterNetworkV6)
return true;
// Hostname or domain
return HostName.IsMatch(s);
}
public static bool IsValidQualifiedClassName(string value, bool requireNamespace, bool allowVerbatimIdentifiers)
{
if (string.IsNullOrWhiteSpace(value))
return false;
string s = value.Trim();
if (s.Length == 0)
return false;
// Reject whitespace inside the name
for (int i = 0; i < s.Length; i++)
{
if (char.IsWhiteSpace(s[i]))
return false;
}
// Optional source-style prefix: global::Namespace.Type
if (s.StartsWith("global::", StringComparison.Ordinal))
s = s.Substring("global::".Length);
string[] parts = s.Split('.');
if (requireNamespace && parts.Length < 2)
return false;
for (int i = 0; i < parts.Length; i++)
{
if (!IsValidIdentifier(parts[i], allowVerbatimIdentifiers))
return false;
}
return true;
}
private static bool IsValidIdentifier(string identifier, bool allowVerbatimIdentifier)
{
if (string.IsNullOrEmpty(identifier))
return false;
string id = identifier;
if (id[0] == '@')
{
if (!allowVerbatimIdentifier)
return false;
id = id.Substring(1);
if (id.Length == 0)
return false;
}
if (!IsIdentifierStartCharacter(id[0]))
return false;
for (int i = 1; i < id.Length; i++)
{
if (!IsIdentifierPartCharacter(id[i]))
return false;
}
// Reject reserved keywords unless written as @keyword
if (identifier[0] != '@' && ReservedKeywords.Contains(id))
return false;
return true;
}
private static bool IsIdentifierStartCharacter(char ch)
{
if (ch == '_')
return true;
UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory(ch);
return category == UnicodeCategory.UppercaseLetter ||
category == UnicodeCategory.LowercaseLetter ||
category == UnicodeCategory.TitlecaseLetter ||
category == UnicodeCategory.ModifierLetter ||
category == UnicodeCategory.OtherLetter ||
category == UnicodeCategory.LetterNumber;
}
private static bool IsIdentifierPartCharacter(char ch)
{
if (IsIdentifierStartCharacter(ch))
return true;
UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory(ch);
return category == UnicodeCategory.DecimalDigitNumber ||
category == UnicodeCategory.ConnectorPunctuation ||
category == UnicodeCategory.NonSpacingMark ||
category == UnicodeCategory.SpacingCombiningMark ||
category == UnicodeCategory.Format;
}
} }
} }
+93 -9
View File
@@ -82,8 +82,8 @@ public class Warehouse
KeyList<string, KeyList<ulong, RemoteTypeDef>> _remoteTypeDefs KeyList<string, KeyList<ulong, RemoteTypeDef>> _remoteTypeDefs
= new KeyList<string, KeyList<ulong, RemoteTypeDef>>(); = new KeyList<string, KeyList<ulong, RemoteTypeDef>>();
//KeyList<string, KeyList<TypeDefKind, KeyList<uint, RemoteTypeDef>>> _remoteTypeDefs // Domain -> Kind -> Type Name -> Proxy Type
// = new KeyList<string, KeyList<TypeDefKind, KeyList<uint, RemoteTypeDef>>>(); KeyList<string, KeyList<TypeDefKind, KeyList<string, Type>>> _proxyTypeDefs = new();
Map<string, IAuthenticationProvider> _authenticationProviders = new Map<string, IAuthenticationProvider>(); Map<string, IAuthenticationProvider> _authenticationProviders = new Map<string, IAuthenticationProvider>();
@@ -579,14 +579,98 @@ public class Warehouse
} }
public void IsProxyType(Type type) public Type TryGetProxyType(TypeDefKind kind, string domain, string name)
{ {
if (!_proxyTypeDefs.ContainsKey(domain))
return null;
if (!_proxyTypeDefs[domain].ContainsKey(kind))
return null;
if (!_proxyTypeDefs[domain][kind].ContainsKey(name))
return null;
return _proxyTypeDefs[domain][kind][name];
} }
public Type GetProxyType(TypeDefKind kind, string domain, string name)
{
if (!_proxyTypeDefs.ContainsKey(domain))
throw new Exception($"No proxy types registered for domain {domain}.");
if (!_proxyTypeDefs[domain].ContainsKey(kind))
throw new Exception($"No proxy types registered for kind {kind} in domain {domain}.");
if (!_proxyTypeDefs[domain][kind].ContainsKey(name))
throw new Exception($"No proxy type registered with name {name} for kind {kind} in domain {domain}.");
return _proxyTypeDefs[domain][kind][name];
}
public void RegisterProxyType(Type type) public void RegisterProxyType(Type type)
{ {
// make sure the type has remote attribute
var remoteAttr = type.GetCustomAttribute<RemoteAttribute>();
if (remoteAttr == null)
throw new Exception("Proxy type must have Remote attribute.");
//@TODO should add this check t the RemoteAttribute class and use it here, but for now, we will just check the domain and full name format here.
if (!remoteAttr.AreValidDomains())
throw new Exception("Invalid domain in Remote attribute.");
if (!remoteAttr.IsValidFullName())
throw new Exception("Invalid full name in Remote attribute.");
// make sure the type implements IResource or IRecord
if (Codec.ImplementsInterface(type, typeof(IRecord)))
{
foreach (var domain in remoteAttr.Domains)
{
if (!_proxyTypeDefs.ContainsKey(domain))
_proxyTypeDefs.Add(domain, new KeyList<TypeDefKind, KeyList<string, Type>>());
if (!_proxyTypeDefs[domain].ContainsKey(TypeDefKind.Record))
_proxyTypeDefs[domain][TypeDefKind.Record] = new KeyList<string, Type>();
_proxyTypeDefs[domain][TypeDefKind.Record][remoteAttr.FullName] = type;
}
}
else if (Codec.InheritsClass(type, typeof(EpResource)))
{
foreach (var domain in remoteAttr.Domains)
{
if (!_proxyTypeDefs.ContainsKey(domain))
_proxyTypeDefs.Add(domain, new KeyList<TypeDefKind, KeyList<string, Type>>());
if (!_proxyTypeDefs[domain].ContainsKey(TypeDefKind.Resource))
_proxyTypeDefs[domain][TypeDefKind.Resource] = new KeyList<string, Type>();
_proxyTypeDefs[domain][TypeDefKind.Resource][remoteAttr.FullName] = type;
}
}
else if (type.IsEnum)
{
foreach (var domain in remoteAttr.Domains)
{
if (!_proxyTypeDefs.ContainsKey(domain))
_proxyTypeDefs.Add(domain, new KeyList<TypeDefKind, KeyList<string, Type>>());
if (!_proxyTypeDefs[domain].ContainsKey(TypeDefKind.Enum))
_proxyTypeDefs[domain][TypeDefKind.Enum] = new KeyList<string, Type>();
_proxyTypeDefs[domain][TypeDefKind.Enum][remoteAttr.FullName] = type;
}
}
else
{
throw new Exception("Proxy type must implement IResource or IRecord or be an enum.");
}
} }
/// <summary> /// <summary>
@@ -759,14 +843,14 @@ public class Warehouse
return _remoteTypeDefs[domain].Values.FirstOrDefault(x => x.Name == typeName); return _remoteTypeDefs[domain].Values.FirstOrDefault(x => x.Name == typeName);
} }
public TypeDef GetRemoteTypeDefByType(Type type) //public TypeDef GetRemoteTypeDefByType(Type type)
{ //{
var remoteAttr = type.GetCustomAttribute<RemoteAttribute>(); // var remoteAttr = type.GetCustomAttribute<RemoteAttribute>();
if (remoteAttr == null) return null; // if (remoteAttr == null) return null;
return GetRemoteTypeDefByName(remoteAttr.Domain, remoteAttr.FullName); // return GetRemoteTypeDefByName(remoteAttr.Domain, remoteAttr.FullName);
} //}
/// <summary> /// <summary>
/// Get a TypeDef by type name . If not in the warehouse, a new TypeDef is created and added to the warehouse. /// Get a TypeDef by type name . If not in the warehouse, a new TypeDef is created and added to the warehouse.
+4 -1
View File
@@ -16,10 +16,13 @@ namespace Esiur.Tests.RPC.Client
var rt = new TestResults(); var rt = new TestResults();
using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id); using var mon = new PerProcessNetMonitor(Process.GetCurrentProcess().Id);
//mon.Start(); mon.Start();
Console.WriteLine($"\n== Esiur @ {address} =="); Console.WriteLine($"\n== Esiur @ {address} ==");
// register proxy types
Initialization.RegisterTypes(Warehouse.Default);
var service = await Warehouse.Default.Get<Service>(address); var service = await Warehouse.Default.Get<Service>(address);
var sock = service.ResourceConnection.Socket as TcpSocket; var sock = service.ResourceConnection.Socket as TcpSocket;
@@ -6,7 +6,7 @@ using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Address", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Address", "localhost")]
[Export] [Export]
public class Address : IRecord public class Address : IRecord
{ {
@@ -6,7 +6,7 @@ using Google.Protobuf;
using System; using System;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Attachment", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Attachment", "localhost")]
[Export] [Export]
public class Attachment : IRecord public class Attachment : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.BusinessDocument", "")] [Remote("Esiur.Tests.RPC.EsiurServer.BusinessDocument", "localhost")]
[Export] [Export]
public class BusinessDocument : IRecord public class BusinessDocument : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Currency", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Currency", "localhost")]
[Export] [Export]
public enum Currency public enum Currency
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.DocType", "")] [Remote("Esiur.Tests.RPC.EsiurServer.DocType", "localhost")]
[Export] [Export]
public enum DocType public enum DocType
{ {
@@ -6,7 +6,7 @@ using Google.Protobuf;
using System; using System;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.DocumentHeader", "")] [Remote("Esiur.Tests.RPC.EsiurServer.DocumentHeader", "localhost")]
[Export] [Export]
public class DocumentHeader : IRecord public class DocumentHeader : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Kind", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Kind", "localhost")]
[Export] [Export]
public enum Kind public enum Kind
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.LineItem", "")] [Remote("Esiur.Tests.RPC.EsiurServer.LineItem", "localhost")]
[Export] [Export]
public class LineItem : IRecord public class LineItem : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.LineType", "")] [Remote("Esiur.Tests.RPC.EsiurServer.LineType", "localhost")]
[Export] [Export]
public enum LineType public enum LineType
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Party", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Party", "localhost")]
[Export] [Export]
public class Party : IRecord public class Party : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Payment", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Payment", "localhost")]
[Export] [Export]
public class Payment : IRecord public class Payment : IRecord
{ {
@@ -5,7 +5,7 @@ using Esiur.Data;
using Esiur.Protocol; using Esiur.Protocol;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.PaymentMethod", "")] [Remote("Esiur.Tests.RPC.EsiurServer.PaymentMethod", "localhost")]
[Export] [Export]
public enum PaymentMethod public enum PaymentMethod
{ {
@@ -6,7 +6,7 @@ using Esiur.Protocol;
#nullable enable #nullable enable
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Service", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Service", "localhost")]
public class Service : EpResource public class Service : EpResource
{ {
public Service(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { } public Service(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { }
@@ -6,7 +6,7 @@ using Esiur.Protocol;
#nullable enable #nullable enable
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.TestObject", "")] [Remote("Esiur.Tests.RPC.EsiurServer.TestObject", "localhost")]
public class TestObject : EpResource public class TestObject : EpResource
{ {
public TestObject(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { } public TestObject(EpConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) { }
@@ -6,7 +6,7 @@ using Google.Protobuf;
using System; using System;
namespace Esiur.Tests.RPC.EsiurServer namespace Esiur.Tests.RPC.EsiurServer
{ {
[Remote("Esiur.Tests.RPC.EsiurServer.Variant", "")] [Remote("Esiur.Tests.RPC.EsiurServer.Variant", "localhost")]
[Export] [Export]
public class Variant : IRecord public class Variant : IRecord
{ {
-8
View File
@@ -1,8 +0,0 @@
using System;
namespace Esiur {
public static class Generated {
public static Type[] Resources {get;} = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.Service),typeof(Esiur.Tests.RPC.EsiurServer.TestObject) };
public static Type[] Records { get; } = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.BusinessDocument),typeof(Esiur.Tests.RPC.EsiurServer.Attachment),typeof(Esiur.Tests.RPC.EsiurServer.Party),typeof(Esiur.Tests.RPC.EsiurServer.Address),typeof(Esiur.Tests.RPC.EsiurServer.DocumentHeader),typeof(Esiur.Tests.RPC.EsiurServer.LineItem),typeof(Esiur.Tests.RPC.EsiurServer.Variant),typeof(Esiur.Tests.RPC.EsiurServer.Payment) };
public static Type[] Enums { get; } = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.Currency),typeof(Esiur.Tests.RPC.EsiurServer.DocType),typeof(Esiur.Tests.RPC.EsiurServer.Kind),typeof(Esiur.Tests.RPC.EsiurServer.LineType),typeof(Esiur.Tests.RPC.EsiurServer.PaymentMethod) };
}
}
@@ -0,0 +1,24 @@
using Esiur.Resource;
using System;
namespace Esiur.Tests.RPC.EsiurServer
{
public static class Initialization
{
public static Type[] Resources { get; } = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.Service), typeof(Esiur.Tests.RPC.EsiurServer.TestObject) };
public static Type[] Records { get; } = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.BusinessDocument), typeof(Esiur.Tests.RPC.EsiurServer.Attachment), typeof(Esiur.Tests.RPC.EsiurServer.Party), typeof(Esiur.Tests.RPC.EsiurServer.Address), typeof(Esiur.Tests.RPC.EsiurServer.DocumentHeader), typeof(Esiur.Tests.RPC.EsiurServer.LineItem), typeof(Esiur.Tests.RPC.EsiurServer.Variant), typeof(Esiur.Tests.RPC.EsiurServer.Payment) };
public static Type[] Enums { get; } = new Type[] { typeof(Esiur.Tests.RPC.EsiurServer.Currency), typeof(Esiur.Tests.RPC.EsiurServer.DocType), typeof(Esiur.Tests.RPC.EsiurServer.Kind), typeof(Esiur.Tests.RPC.EsiurServer.LineType), typeof(Esiur.Tests.RPC.EsiurServer.PaymentMethod) };
public static void RegisterTypes(Warehouse warehouse)
{
foreach(var type in Resources)
warehouse.RegisterProxyType(type);
foreach(var type in Records)
warehouse.RegisterProxyType(type);
foreach(var type in Enums)
warehouse.RegisterProxyType(type);
}
}
}