forked from PHOENIXCONTACT/MORYX-Framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathResource.cs
153 lines (130 loc) · 4.53 KB
/
Resource.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) 2023, Phoenix Contact GmbH & Co. KG
// Licensed under the Apache License, Version 2.0
using System;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
using Moryx.Logging;
using Moryx.Modules;
using Moryx.Serialization;
namespace Moryx.AbstractionLayer.Resources
{
/// <summary>
/// Base class for all resources to reduce boilerplate code
/// </summary>
[DataContract, EntrySerialize(EntrySerializeMode.Never)]
public abstract class Resource : ILoggingComponent, IResource, IInitializablePlugin, IDisposable, IPersistentObject
{
#region Dependencies
/// <summary>
/// Logger for this resource
/// </summary>
public IModuleLogger Logger { get; set; }
/// <summary>
/// Reference to the graph for interaction
/// </summary>
public IResourceGraph Graph { get; set; }
#endregion
/// <summary>Database key of the resource</summary>
public long Id { get; set; }
/// <inheritdoc />
public string Name { get; set; }
/// <summary>
/// Description of this resource
/// </summary>
public string Description { get; set; }
/// <summary>
/// Descriptor to provide access to this resource. Either the descriptor or
/// its properties and methods need to flagged with <see cref="EntrySerializeAttribute"/>
/// </summary>
public virtual object Descriptor => this;
/// <summary>
/// Parent resource of this resource
/// </summary>
[ResourceReference(ResourceRelationType.ParentChild, ResourceReferenceRole.Source)]
public Resource Parent { get; set; }
/// <summary>
/// All children of this resource
/// </summary>
[ResourceReference(ResourceRelationType.ParentChild, ResourceReferenceRole.Target)]
public IReferences<Resource> Children { get; set; }
/// <inheritdoc />
void IInitializable.Initialize()
{
var loggerName = Name?.Replace(".", "_"); // replace . with _ because of logger child structure
Logger = Logger?.GetChild(loggerName, GetType());
OnInitialize();
}
/// <summary>
/// Resource specific implementation of <see cref="IInitializable.Initialize"/>
/// </summary>
protected virtual void OnInitialize()
{
}
/// <inheritdoc />
void IPlugin.Start()
{
OnStart();
}
/// <summary>
/// Resource specific implementation of <see cref="IPlugin.Start"/>
/// </summary>
protected virtual void OnStart()
{
}
/// <inheritdoc />
void IPlugin.Stop()
{
OnStop();
}
/// <summary>
/// Resource specific implementation of <see cref="IPlugin.Stop"/>
/// </summary>
protected virtual void OnStop()
{
}
/// <inheritdoc />
void IDisposable.Dispose()
{
// Remove graph reference, just to make sure
Graph = null;
try
{
OnDispose();
}
catch (Exception e)
{
Logger?.Log(LogLevel.Error, e, "Failed to dispose resource {0}-{1}", Id, Name);
}
}
/// <summary>
/// Resource specific implementation of Dispose instead of overriding <see cref="IDisposable.Dispose"/>.
/// This ensures, that developers do not accidentally forget to call <code>base.Dispose()</code> and
/// create a memory leak
/// </summary>
protected virtual void OnDispose()
{
}
/// <summary>
/// Inform the resource management, that this instance was modified
/// and trigger saving the current state to storage
/// </summary>
protected void RaiseResourceChanged()
{
// This is only null during boot, when the resource manager populates the object
Changed?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Return Id, name and type of the resource
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"{Id}:{Name} ({GetType().Name})";
}
/// <summary>
/// Event raised when the resource was modified and the changes should be
/// written to the data storage
/// </summary>
public event EventHandler Changed;
}
}