Append discovery service

pull/1/head
a.bozhenov 6 years ago
parent 4d556fbe10
commit 5484c32f65

@ -0,0 +1,21 @@
using System;
using ZeroLevel;
using ZeroLevel.Services.Applications;
namespace TestApp
{
public class MyService
: BaseZeroService
{
protected override void StartAction()
{
Log.Info("Started");
Sheduller.RemindEvery(TimeSpan.FromSeconds(5), () => Log.Info("Still alive"));
}
protected override void StopAction()
{
Log.Info("Stopped");
}
}
}

@ -0,0 +1,13 @@
using ZeroLevel;
namespace TestApp
{
internal static class Program
{
private static void Main(string[] args)
{
Log.AddConsoleLogger();
Bootstrap.Startup<MyService>(args);
}
}
}

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,37 @@
using System.Collections.Generic;
using ZeroLevel.Models;
using ZeroLevel.Network;
using ZeroLevel.Services.Applications;
namespace ZeroLevel.Discovery
{
public sealed class DiscoveryService
: BaseZeroService
{
private IExService _exInbox;
public DiscoveryService()
: base("Discovery")
{
}
protected override void StartAction()
{
var routeTable = new RouteTable();
Injector.Default.Register<RouteTable>(routeTable);
var socketPort = Configuration.Default.First<int>("socketport");
_exInbox = ExchangeTransportFactory.GetServer(socketPort);
_exInbox.RegisterInbox<IEnumerable<ServiceEndpointsInfo>>("services", (_, __) => routeTable.Get());
_exInbox.RegisterInbox<ExServiceInfo, InvokeResult>("register", (info, _, client) => routeTable.Append(info, client));
Log.Info($"TCP server started {_exInbox.Endpoint.Address}:{socketPort}");
}
protected override void StopAction()
{
_exInbox.Dispose();
}
}
}

@ -0,0 +1,11 @@
namespace ZeroLevel.Discovery
{
internal static class Program
{
private static void Main(string[] args)
{
Log.AddConsoleLogger(Services.Logging.LogLevel.System | Services.Logging.LogLevel.FullDebug);
Bootstrap.Startup<DiscoveryService>(args);
}
}
}

@ -0,0 +1,222 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using ZeroLevel.Models;
using ZeroLevel.Network;
namespace ZeroLevel.Discovery
{
public class RouteTable
: IDisposable
{
private readonly Dictionary<string, ServiceEndpointsInfo> _table = new Dictionary<string, ServiceEndpointsInfo>();
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public RouteTable()
{
Load();
Sheduller.RemindEvery(TimeSpan.FromSeconds(10), Heartbeat);
}
#region Snapshot
private static readonly object _snapshot_lock = new object();
private void Save()
{
string snapshot;
_lock.EnterReadLock();
try
{
snapshot = JsonConvert.SerializeObject(_table);
}
catch (Exception ex)
{
Log.Error(ex, "Fault make snapshot");
return;
}
finally
{
_lock.ExitReadLock();
}
try
{
var snapshot_path = Path.Combine(Configuration.BaseDirectory, "snapshot.snp");
lock (_snapshot_lock)
{
File.WriteAllText(snapshot_path, snapshot);
}
}
catch (Exception ex)
{
Log.Error(ex, "Fault save shapshot");
}
}
private void Load()
{
try
{
var path = Path.Combine(Configuration.BaseDirectory, "snapshot.snp");
if (File.Exists(path))
{
var snapshot = File.ReadAllText(path);
if (string.IsNullOrWhiteSpace(snapshot) == false)
{
var restored = JsonConvert.DeserializeObject<Dictionary<string, ServiceEndpointsInfo>>(snapshot);
_lock.EnterWriteLock();
try
{
_table.Clear();
foreach (var r in restored)
{
_table.Add(r.Key, r.Value);
}
}
finally
{
_lock.ExitWriteLock();
}
}
}
}
catch (Exception ex)
{
Log.Error(ex, "Fault load snapshot");
}
}
#endregion Snapshot
private void Heartbeat(long taskid)
{
try
{
var removeEntities = new Dictionary<string, List<string>>();
_lock.EnterReadLock();
try
{
foreach (var pair in _table)
{
var endpointsToRemove = new List<string>();
foreach (var e in pair.Value.Endpoints)
{
if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(e)) == false)
{
if (false == removeEntities.ContainsKey(pair.Key))
{
removeEntities.Add(pair.Key, new List<string>());
}
removeEntities[pair.Key].Add(e);
}
}
}
}
finally
{
_lock.ExitReadLock();
}
_lock.EnterWriteLock();
try
{
foreach (var pair in removeEntities)
{
foreach (var ep in pair.Value)
{
_table[pair.Key].Endpoints.Remove(ep);
}
}
var badKeys = _table.Where(f => f.Value.Endpoints.Count == 0)
.Select(pair => pair.Key)
.ToList();
foreach (var badKey in badKeys)
{
_table.Remove(badKey);
}
}
finally
{
_lock.ExitWriteLock();
}
}
catch (Exception ex)
{
Log.Error(ex, "Fault heartbeat");
}
Save();
}
public InvokeResult Append(ExServiceInfo serviceInfo, IZBackward client)
{
InvokeResult result = null;
var endpoint = $"{client.Endpoint.Address}:{serviceInfo.Port}";
Log.Info($"Regiter request from {endpoint}. Service {serviceInfo?.ServiceKey}");
if (NetUtils.TestConnection(NetUtils.CreateIPEndPoint(endpoint)))
{
var key = $"{serviceInfo.ServiceGroup}:{serviceInfo.ServiceType}:{serviceInfo.ServiceKey.Trim().ToLowerInvariant()}";
_lock.EnterWriteLock();
try
{
if (false == _table.ContainsKey(key))
{
_table.Add(key, new ServiceEndpointsInfo
{
ServiceKey = serviceInfo.ServiceKey,
Version = serviceInfo.Version,
ServiceGroup = serviceInfo.ServiceGroup,
ServiceType = serviceInfo.ServiceType,
Endpoints = new List<string>()
});
_table[key].Endpoints.Add(endpoint);
Log.Info($"The service '{serviceInfo.ServiceKey}' registered on endpoint: {endpoint}");
}
else
{
var exists = _table[key];
if (exists.Endpoints.Contains(endpoint) == false)
{
Log.Info($"The service '{serviceInfo.ServiceKey}' register endpoint: {endpoint}");
exists.Endpoints.Add(endpoint);
}
}
}
catch (Exception ex)
{
Log.Error(ex, $"Fault append service ({serviceInfo.ServiceKey} {serviceInfo.Version}) endpoint '{endpoint}'");
result = InvokeResult.Fault(ex.Message);
}
finally
{
_lock.ExitWriteLock();
}
Save();
result = InvokeResult.Succeeding();
}
else
{
result = InvokeResult.Fault($"Appending endpoint '{endpoint}' canceled for service {serviceInfo.ServiceKey} ({serviceInfo.Version}) because endpoind no avaliable");
}
return result;
}
public IEnumerable<ServiceEndpointsInfo> Get()
{
_lock.EnterReadLock();
try
{
return _table.Values.ToList();
}
finally
{
_lock.ExitReadLock();
}
}
public void Dispose()
{
_lock.Dispose();
}
}
}

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ZeroLevel\ZeroLevel.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="socketport" value="5012"/>
</appSettings>
</configuration>

@ -27,6 +27,11 @@ namespace ZeroArrayExtensionsTest
if (string.Compare(this.Title, other.Title, StringComparison.OrdinalIgnoreCase) != 0) return false;
return this.Num == other.Num;
}
public override int GetHashCode()
{
return Num.GetHashCode();
}
}
[Fact]

@ -20,11 +20,11 @@ namespace ZeroInvokingTest
var identityGetDateTime = invoker.GetInvokerIdentity("GetDateTime", new Type[] { typeof(DateTime) });
var identityGetHelp = invoker.GetInvokerIdentity("GetHelp", null);
// Assert
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }), "hello");
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }), 100);
Assert.Equal("hello", invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }));
Assert.Equal(100, invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }));
var date = DateTime.Now;
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }), date);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetHelp), "help");
Assert.Equal(date, invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }));
Assert.Equal("help", invoker.Invoke(new FakeClass(), identityGetHelp));
}
[Fact]
@ -42,10 +42,10 @@ namespace ZeroInvokingTest
var identityGetDateTime = invoker.GetInvokerIdentity("GetDateTime", new Type[] { typeof(DateTime) });
var identityGetHelp = invoker.GetInvokerIdentity("GetHelp", null);
// Assert
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }), 100);
Assert.Equal(100, invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }));
var date = DateTime.Now;
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }), date);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetHelp), "help");
Assert.Equal(date, invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }));
Assert.Equal("help", invoker.Invoke(new FakeClass(), identityGetHelp));
}
[Fact]
@ -61,9 +61,9 @@ namespace ZeroInvokingTest
var identityGetHelp = invoker.GetInvokerIdentity("GetHelp", null);
// Assert
var date = DateTime.Now;
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }), date);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }), 100);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetHelp), "help");
Assert.Equal(date, invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }));
Assert.Equal(100, invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }));
Assert.Equal("help", invoker.Invoke(new FakeClass(), identityGetHelp));
}
[Fact]
@ -84,11 +84,11 @@ namespace ZeroInvokingTest
var identityGetDateTime = invoker.GetInvokerIdentity("GetDateTime", new Type[] { typeof(DateTime) });
var identityGetHelp = invoker.GetInvokerIdentity("GetHelp", null);
// Assert
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }), "hello");
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }), 100);
Assert.Equal("hello", invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }));
Assert.Equal(100, invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }));
var date = DateTime.Now;
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }), date);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetHelp), "help");
Assert.Equal(date, invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }));
Assert.Equal("help", invoker.Invoke(new FakeClass(), identityGetHelp));
}
[Fact]
@ -106,11 +106,11 @@ namespace ZeroInvokingTest
var identityGetDateTime = invoker.GetInvokerIdentity("GetDateTime", new Type[] { typeof(DateTime) });
var identityGetHelp = invoker.GetInvokerIdentity("GetHelp", null);
// Assert
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }), "hello");
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }), 100);
Assert.Equal("hello", invoker.Invoke(new FakeClass(), identityGetString, new object[] { "hello" }));
Assert.Equal(100, invoker.Invoke(new FakeClass(), identityGetNumber, new object[] { 100 }));
var date = DateTime.Now;
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }), date);
Assert.Equal(invoker.Invoke(new FakeClass(), identityGetHelp), "help");
Assert.Equal(date, invoker.Invoke(new FakeClass(), identityGetDateTime, new object[] { date }));
Assert.Equal("help", invoker.Invoke(new FakeClass(), identityGetHelp));
}
[Fact]
@ -126,8 +126,8 @@ namespace ZeroInvokingTest
var identityGetNumber = invoker.GetInvokerIdentity("GetNumber", new Type[] { typeof(int) });
var identityGetDateTime = invoker.GetInvokerIdentity("GetDateTime", new Type[] { typeof(DateTime) });
// Assert
Assert.Equal(invoker.InvokeStatic(identityGetString, new object[] { "hello" }), "hello");
Assert.Equal(invoker.InvokeStatic(identityGetNumber, new object[] { 100 }), 100);
Assert.Equal("hello", invoker.InvokeStatic(identityGetString, new object[] { "hello" }));
Assert.Equal(100, invoker.InvokeStatic(identityGetNumber, new object[] { 100 }));
var date = DateTime.Now;
Assert.Equal(invoker.InvokeStatic(identityGetDateTime, new object[] { date }), date);
}

@ -22,17 +22,17 @@ namespace ZeroMappingTest
Assert.True(mapper.Exists("Title"));
Assert.True(mapper.Exists("Description"));
Assert.True(list.Contains("Id"));
Assert.True(list.Contains("Title"));
Assert.True(list.Contains("Description"));
Assert.Contains<string>(list, s => s.Equals("Id", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Title", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Description", StringComparison.Ordinal));
Assert.False(mapper.Exists("Version"));
Assert.False(mapper.Exists("Created"));
Assert.False(list.Contains("Version"));
Assert.False(list.Contains("Created"));
Assert.DoesNotContain<string>(list, s => s.Equals("Version", StringComparison.Ordinal));
Assert.DoesNotContain<string>(list, s => s.Equals("Created", StringComparison.Ordinal));
Assert.Equal(mapper.EntityType, typeof(BaseClass));
Assert.Equal(typeof(BaseClass), mapper.EntityType);
}
[Fact]
@ -52,23 +52,23 @@ namespace ZeroMappingTest
Assert.True(mapper.Exists("ReadOnlyProperty"));
Assert.True(mapper.Exists("WriteOnlyProperty"));
Assert.True(list.Contains("Id"));
Assert.True(list.Contains("Title"));
Assert.True(list.Contains("Description"));
Assert.True(list.Contains("Number"));
Assert.True(list.Contains("Balance"));
Assert.True(list.Contains("ReadOnlyProperty"));
Assert.True(list.Contains("WriteOnlyProperty"));
Assert.Contains<string>(list, s => s.Equals("Id", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Title", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Description", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Number", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("Balance", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("ReadOnlyProperty", StringComparison.Ordinal));
Assert.Contains<string>(list, s => s.Equals("WriteOnlyProperty", StringComparison.Ordinal));
Assert.False(mapper.Exists("HiddenField"));
Assert.False(mapper.Exists("Version"));
Assert.False(mapper.Exists("Created"));
Assert.False(list.Contains("HiddenField"));
Assert.False(list.Contains("Version"));
Assert.False(list.Contains("Created"));
Assert.DoesNotContain<string>(list, s => s.Equals("HiddenField", StringComparison.Ordinal));
Assert.DoesNotContain<string>(list, s => s.Equals("Version", StringComparison.Ordinal));
Assert.DoesNotContain<string>(list, s => s.Equals("Created", StringComparison.Ordinal));
Assert.Equal(mapper.EntityType, typeof(ChildClass));
Assert.Equal(typeof(ChildClass), mapper.EntityType);
}
[Fact]
@ -93,13 +93,13 @@ namespace ZeroMappingTest
mapper.Set(instance, "Title", title);
mapper.Set(instance, "Description", description);
// Assert
Assert.Equal<Guid>(mapper.Get<Guid>(instance, "Id"), id);
Assert.Equal<string>(mapper.Get<string>(instance, "Title"), title);
Assert.Equal<string>(mapper.Get<string>(instance, "Description"), description);
Assert.Equal<Guid>(id, mapper.Get<Guid>(instance, "Id"));
Assert.Equal(title, mapper.Get<string>(instance, "Title"));
Assert.Equal(description, mapper.Get<string>(instance, "Description"));
Assert.Equal(mapper.Get(instance, "Id"), id);
Assert.Equal(mapper.Get(instance, "Title"), title);
Assert.Equal(mapper.Get(instance, "Description"), description);
Assert.Equal(id, mapper.Get(instance, "Id"));
Assert.Equal(title, mapper.Get(instance, "Title"));
Assert.Equal(description, mapper.Get(instance, "Description"));
try
{
@ -140,8 +140,8 @@ namespace ZeroMappingTest
mapper.Set(instance, "Balance", balance);
// Assert
Assert.Equal<Guid>(mapper.Get<Guid>(instance, "Id"), id);
Assert.Equal<string>(mapper.Get<string>(instance, "Title"), title);
Assert.Equal<string>(mapper.Get<string>(instance, "Description"), description);
Assert.Equal(mapper.Get<string>(instance, "Title"), title);
Assert.Equal(mapper.Get<string>(instance, "Description"), description);
Assert.Equal<int>(mapper.Get<int>(instance, "Number"), number);
Assert.Equal<int>(mapper.Get<int>(instance, "Balance"), balance);
@ -185,7 +185,7 @@ namespace ZeroMappingTest
{
mapper.Get(instance, "Number");
}
catch(Exception ex)
catch (Exception ex)
{
Assert.True(false, ex.Message);
}
@ -214,15 +214,15 @@ namespace ZeroMappingTest
var obj = new PocoFields { Id = 1000, Date = date, Title = "Caption" };
// Assert
Assert.Equal(mapper.EntityType, typeof(PocoFields));
Assert.Equal(typeof(PocoFields), mapper.EntityType);
Assert.True(mapper.Exists("Id"));
Assert.True(mapper.Exists("Date"));
Assert.True(mapper.Exists("Title"));
Assert.Equal(mapper.Get(obj, "Id"), (long)1000);
Assert.Equal(mapper.Get(obj, "Date"), date);
Assert.Equal(mapper.Get(obj, "Title"), "Caption");
Assert.Equal((long)1000, mapper.Get(obj, "Id"));
Assert.Equal(date, mapper.Get(obj, "Date"));
Assert.Equal("Caption", mapper.Get(obj, "Title"));
mapper.Set(obj, "Id", 1001);
Assert.Equal(mapper.Get(obj, "Id"), (long)1001);
@ -237,15 +237,15 @@ namespace ZeroMappingTest
var obj = new PocoProperties { Id = 1000, Date = date, Title = "Caption" };
// Assert
Assert.Equal(mapper.EntityType, typeof(PocoProperties));
Assert.Equal(typeof(PocoProperties), mapper.EntityType);
Assert.True(mapper.Exists("Id"));
Assert.True(mapper.Exists("Date"));
Assert.True(mapper.Exists("Title"));
Assert.Equal(mapper.Get(obj, "Id"), (long)1000);
Assert.Equal(mapper.Get(obj, "Date"), date);
Assert.Equal(mapper.Get(obj, "Title"), "Caption");
Assert.Equal((long)1000, mapper.Get(obj, "Id"));
Assert.Equal(date, mapper.Get(obj, "Date"));
Assert.Equal("Caption", mapper.Get(obj, "Title"));
mapper.Set(obj, "Id", 1001);
Assert.Equal(mapper.Get(obj, "Id"), (long)1001);

@ -57,11 +57,11 @@ namespace ZeroSpecificationPatternsTest
Title = "Title #3"
});
Assert.True(a1.Success);
Assert.Equal<long>(a1.Count, 1);
Assert.Equal<long>(1, a1.Count);
Assert.True(a2.Success);
Assert.Equal<long>(a2.Count, 1);
Assert.Equal<long>(1, a2.Count);
Assert.True(a3.Success);
Assert.Equal<long>(a3.Count, 1);
Assert.Equal<long>(1, a3.Count);
}
[Fact]
@ -100,7 +100,7 @@ namespace ZeroSpecificationPatternsTest
{
var ar = storage.Post(i);
Assert.True(ar.Success);
Assert.Equal<long>(ar.Count, 1);
Assert.Equal<long>(1, ar.Count);
}
// Test equals set and storage data
foreach (var i in storage.Get())
@ -156,7 +156,7 @@ namespace ZeroSpecificationPatternsTest
{
var ar = storage.Post(i);
Assert.True(ar.Success);
Assert.Equal<long>(ar.Count, 1);
Assert.Equal<long>(1, ar.Count);
}
// Test equals set and storage data
foreach (var i in storage.Get())
@ -168,21 +168,21 @@ namespace ZeroSpecificationPatternsTest
Assert.True(set.Exists(dto => TestDTOEqual(i, dto)));
}
var result_eq = storage.Get(Query.EQ("Title", "Title #1"));
Assert.Equal<int>(result_eq.Count(), 1);
Assert.Single(result_eq);
Assert.True(TestDTOEqual(set[0], result_eq.First()));
var result_neq = storage.Get(Query.NEQ("Title", "Title #1"));
Assert.Equal<int>(result_neq.Count(), 2);
Assert.Equal<int>(2, result_neq.Count());
Assert.True(TestDTOEqual(set[1], result_neq.First()));
Assert.True(TestDTOEqual(set[2], result_neq.Skip(1).First()));
var result_gt = storage.Get(Query.GT("Number", 1));
Assert.Equal<int>(result_gt.Count(), 2);
Assert.Equal<int>(2, result_gt.Count());
Assert.True(TestDTOEqual(set[0], result_gt.First()));
Assert.True(TestDTOEqual(set[2], result_gt.Skip(1).First()));
var result_lt = storage.Get(Query.LT("Number", 1));
Assert.Equal<int>(result_lt.Count(), 1);
Assert.Single(result_lt);
Assert.True(TestDTOEqual(set[1], result_lt.First()));
}
}

@ -5,7 +5,11 @@ VisualStudioVersion = 15.0.28307.421
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel", "ZeroLevel\ZeroLevel.csproj", "{06C9E60E-D449-41A7-9BF0-A829AAF5D214}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZeroLevel.UnitTests", "ZeroLevel.UnitTests\ZeroLevel.UnitTests.csproj", "{E5595DE0-B177-4078-AD10-8D3135014838}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.UnitTests", "ZeroLevel.UnitTests\ZeroLevel.UnitTests.csproj", "{E5595DE0-B177-4078-AD10-8D3135014838}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp", "TestApp\TestApp.csproj", "{674561F2-A3E2-40E6-8E5B-AD94276AD856}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZeroLevel.Discovery", "ZeroLevel.Discovery\ZeroLevel.Discovery.csproj", "{5CE51CC9-7884-4E21-9D68-2321CA14312E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,6 +25,14 @@ Global
{E5595DE0-B177-4078-AD10-8D3135014838}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5595DE0-B177-4078-AD10-8D3135014838}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5595DE0-B177-4078-AD10-8D3135014838}.Release|Any CPU.Build.0 = Release|Any CPU
{674561F2-A3E2-40E6-8E5B-AD94276AD856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{674561F2-A3E2-40E6-8E5B-AD94276AD856}.Debug|Any CPU.Build.0 = Debug|Any CPU
{674561F2-A3E2-40E6-8E5B-AD94276AD856}.Release|Any CPU.ActiveCfg = Release|Any CPU
{674561F2-A3E2-40E6-8E5B-AD94276AD856}.Release|Any CPU.Build.0 = Release|Any CPU
{5CE51CC9-7884-4E21-9D68-2321CA14312E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CE51CC9-7884-4E21-9D68-2321CA14312E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CE51CC9-7884-4E21-9D68-2321CA14312E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CE51CC9-7884-4E21-9D68-2321CA14312E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -64,6 +64,15 @@ namespace ZeroLevel.Models
/// </summary>
public static InvokeResult Succeeding() { return _successResultWitoutComment; }
public static InvokeResult<T> Succeeding<T>(T value, string comment = "")
{
return new InvokeResult<T>(value, true, comment);
}
public static InvokeResult<T> Fault<T>(string comment)
{
return new InvokeResult<T>(false, comment);
}
#endregion Fabric methods
public virtual void Serialize(IBinaryWriter writer)
@ -102,20 +111,6 @@ namespace ZeroLevel.Models
#endregion Ctor
#region Fabric methods
public static InvokeResult<T> Succeeding(T value, string comment = "")
{
return new InvokeResult<T>(value, true, comment);
}
public static InvokeResult<T> Fault<T>(string comment)
{
return new InvokeResult<T>(false, comment);
}
#endregion Fabric methods
public override void Serialize(IBinaryWriter writer)
{
writer.WriteBoolean(this.Success);

Loading…
Cancel
Save

Powered by TurnKey Linux.