Skip to content

Commit 7256a53

Browse files
authored
Merge pull request #807 from PHOENIXCONTACT/rename/resource-api
Renamed GetAllResources, Create, Modify and Read and added remarks
2 parents 1afdb85 + 13de568 commit 7256a53

File tree

18 files changed

+183
-122
lines changed

18 files changed

+183
-122
lines changed

docs/migrations/v8_to_v10.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ The simulator module has also been renamed, and its namespace and package id hav
2222
- ResourceRelationType.CurrentExchangablePart -> ResourceRelationType.CurrentExchangeablePart
2323
- ResourceRelationType.PossibleExchangablePart -> ResourceRelationType.PossibleExchangeablePart
2424
- MqttDriver.BrokerURL -> MqttDriver.BrokerUrl
25+
- IResourceManagement.GetAllResources -> IResourceManagement.GetResourcesUnsafe
26+
- IResourceManagement.Create -> IResourceManagement.CreateUnsafe
27+
- IResourceManagement.Read -> IResourceManagement.ReadUnsafe
28+
- IResourceManagement.Modify -> IResourceManagement.ModifyUnsafe
2529

2630
## Reduction of interfaces
2731

src/Moryx.AbstractionLayer.Resources.Endpoints/ResourceManagementController.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public ActionResult<ResourceModel[]> GetDetailsBatch([FromQuery] long[] ids)
6363
if (ids is null || ids.Length == 0)
6464
ids = _resourceManagement.GetResources<IResource>().Select(r => r.Id).ToArray();
6565

66-
return ids.Select(id => _resourceManagement.Read(id, r => converter.GetDetails(r)))
66+
return ids.Select(id => _resourceManagement.ReadUnsafe(id, r => converter.GetDetails(r)))
6767
.Where(details => details != null).ToArray();
6868
}
6969

@@ -75,10 +75,10 @@ public ActionResult<ResourceModel[]> GetDetailsBatch([FromQuery] long[] ids)
7575
public ActionResult<ResourceModel[]> GetResources(ResourceQuery query)
7676
{
7777
var filter = new ResourceQueryFilter(query, _resourceTypeTree);
78-
var resourceProxies = _resourceManagement.GetAllResources<IResource>(r => filter.Match(r as Resource)).ToArray();
78+
var resourceProxies = _resourceManagement.GetResourcesUnsafe<IResource>(r => filter.Match(r as Resource)).ToArray();
7979

8080
var converter = new ResourceQueryConverter(_resourceTypeTree, _serialization, query);
81-
var values = resourceProxies.Select(p => _resourceManagement.Read(p.Id, r => converter.QueryConversion(r))).Where(details => details != null).ToArray();
81+
var values = resourceProxies.Select(p => _resourceManagement.ReadUnsafe(p.Id, r => converter.QueryConversion(r))).Where(details => details != null).ToArray();
8282
return values;
8383
}
8484

@@ -91,7 +91,7 @@ public ActionResult<ResourceModel[]> GetResources(ResourceQuery query)
9191
public ActionResult<ResourceModel> GetDetails(long id)
9292
{
9393
var converter = new ResourceToModelConverter(_resourceTypeTree, _serialization);
94-
var resourceModel = _resourceManagement.Read(id, r => converter.GetDetails(r));
94+
var resourceModel = _resourceManagement.ReadUnsafe(id, r => converter.GetDetails(r));
9595
if (resourceModel is null)
9696
return NotFound(new MoryxExceptionResponse { Title = string.Format(Strings.ResourceNotFoundException_ById_Message, id) });
9797

@@ -107,13 +107,13 @@ public ActionResult<ResourceModel> GetDetails(long id)
107107
[Authorize(Policy = ResourcePermissions.CanInvokeMethod)]
108108
public ActionResult<Entry> InvokeMethod(long id, string method, Entry parameters)
109109
{
110-
if (_resourceManagement.GetAllResources<IResource>(r => r.Id == id) is null)
110+
if (_resourceManagement.GetResourcesUnsafe<IResource>(r => r.Id == id) is null)
111111
return NotFound(new MoryxExceptionResponse { Title = string.Format(Strings.ResourceNotFoundException_ById_Message, id) });
112112

113113
Entry entry = null;
114114
try
115115
{
116-
_resourceManagement.Modify(id, r =>
116+
_resourceManagement.ModifyUnsafe(id, r =>
117117
{
118118
entry = EntryConvert.InvokeMethod(r.Descriptor, new MethodEntry { Name = method, Parameters = parameters }, _serialization);
119119
return true;
@@ -171,7 +171,7 @@ private ActionResult<ResourceModel> Construct(string type, MethodEntry method)
171171
{
172172
try
173173
{
174-
var id = _resourceManagement.Create(_resourceTypeTree[type].ResourceType, r => EntryConvert.InvokeMethod(r, method, _serialization));
174+
var id = _resourceManagement.CreateUnsafe(_resourceTypeTree[type].ResourceType, r => EntryConvert.InvokeMethod(r, method, _serialization));
175175
return GetDetails(id);
176176
}
177177
catch (Exception e)
@@ -190,16 +190,16 @@ private ActionResult<ResourceModel> Construct(string type, MethodEntry method)
190190
[Authorize(Policy = ResourcePermissions.CanAdd)]
191191
public ActionResult<ResourceModel> Save(ResourceModel model)
192192
{
193-
if (_resourceManagement.GetAllResources<IResource>(r => r.Id == model.Id).Any())
193+
if (_resourceManagement.GetResourcesUnsafe<IResource>(r => r.Id == model.Id).Any())
194194
return Conflict($"The resource '{model.Id}' already exists.");
195195
try
196196
{
197-
var id = _resourceManagement.Create(_resourceTypeTree[model.Type].ResourceType, r =>
197+
var id = _resourceManagement.CreateUnsafe(_resourceTypeTree[model.Type].ResourceType, r =>
198198
{
199199
var resourcesToSave = new HashSet<long>();
200200
var resourceCache = new Dictionary<long, Resource>();
201201
FromModel(model, resourcesToSave, resourceCache, r);
202-
resourcesToSave.Skip(1).ForEach(id => _resourceManagement.Modify(id, r => true));
202+
resourcesToSave.Skip(1).ForEach(id => _resourceManagement.ModifyUnsafe(id, r => true));
203203
});
204204

205205
return GetDetails(id);
@@ -231,11 +231,11 @@ private Resource FromModel(ResourceModel model, HashSet<long> resourcesToSave, D
231231
resource = (Resource)Activator.CreateInstance(_resourceTypeTree[model.Type].ResourceType);
232232
else if (model.Id == 0)
233233
{
234-
var id = _resourceManagement.Create(_resourceTypeTree[model.Type].ResourceType, r => { });
235-
resource = _resourceManagement.Read<Resource>(id, resource => resource);
234+
var id = _resourceManagement.CreateUnsafe(_resourceTypeTree[model.Type].ResourceType, r => { });
235+
resource = _resourceManagement.ReadUnsafe<Resource>(id, resource => resource);
236236
}
237237
else
238-
resource = _resourceManagement.Read<Resource>(model.Id, resource => resource);
238+
resource = _resourceManagement.ReadUnsafe<Resource>(model.Id, resource => resource);
239239

240240
// Write to cache because following calls might only have an empty reference
241241
if (model.Id == 0)
@@ -340,17 +340,17 @@ private void UpdateReferences(Resource instance, HashSet<long> resourcesToSave,
340340
[Authorize(Policy = ResourcePermissions.CanEdit)]
341341
public ActionResult<ResourceModel> Update(long id, ResourceModel model)
342342
{
343-
if (_resourceManagement.GetAllResources<IResource>(r => r.Id == id) is null)
343+
if (_resourceManagement.GetResourcesUnsafe<IResource>(r => r.Id == id) is null)
344344
return NotFound(new MoryxExceptionResponse { Title = string.Format(Strings.ResourceNotFoundException_ById_Message, id) });
345345

346346
try
347347
{
348-
_resourceManagement.Modify(id, r =>
348+
_resourceManagement.ModifyUnsafe(id, r =>
349349
{
350350
var resourcesToSave = new HashSet<long>();
351351
var resourceCache = new Dictionary<long, Resource>();
352352
FromModel(model, resourcesToSave, resourceCache, r);
353-
resourcesToSave.ForEach(id => _resourceManagement.Modify(id, r => true));
353+
resourcesToSave.ForEach(id => _resourceManagement.ModifyUnsafe(id, r => true));
354354
return true;
355355
});
356356
}
@@ -373,7 +373,7 @@ public ActionResult<ResourceModel> Update(long id, ResourceModel model)
373373
[Authorize(Policy = ResourcePermissions.CanDelete)]
374374
public ActionResult Remove(long id)
375375
{
376-
if (_resourceManagement.GetAllResources<IResource>(r => r.Id == id) is null)
376+
if (_resourceManagement.GetResourcesUnsafe<IResource>(r => r.Id == id) is null)
377377
return NotFound(new MoryxExceptionResponse { Title = string.Format(Strings.ResourceNotFoundException_ById_Message, id) });
378378

379379
var deleted = _resourceManagement.Delete(id);

src/Moryx.AbstractionLayer/Resources/IResourceManagement.cs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,69 @@ IEnumerable<TResource> GetResources<TResource>(Func<TResource, bool> predicate)
6363
/// <summary>
6464
/// Get all resources including the private ones of this type that match the predicate
6565
/// </summary>
66-
IEnumerable<TResource> GetAllResources<TResource>(Func<TResource, bool> predicate)
66+
/// <remarks>
67+
/// This method returns the actual resource instances, not wrapped by proxy.
68+
/// As a result, all internal members, including properties and
69+
/// methods not exposed through interfaces, are accessible.
70+
///
71+
/// This API is intended primarily for endpoint controllers that must export or
72+
/// inspect the full internal state of a resource.
73+
///
74+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
75+
/// Use with extreme caution. Do not keep the instances in memory for later usage.
76+
/// </remarks>
77+
IEnumerable<TResource> GetResourcesUnsafe<TResource>(Func<TResource, bool> predicate)
6778
where TResource : class, IResource;
6879

6980
/// <summary>
7081
/// Create and initialize a resource
7182
/// </summary>
72-
long Create(Type resourceType, Action<Resource> initializer);
83+
/// <remarks>
84+
/// The <param name="initializer"></param> action uses the actual resource instance, not wrapped by proxy.
85+
/// As a result, all internal members, including properties and
86+
/// methods not exposed through interfaces, are accessible.
87+
///
88+
/// This API is intended primarily for endpoint controllers that must export or
89+
/// inspect the full internal state of a resource.
90+
///
91+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
92+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
93+
/// </remarks>
94+
long CreateUnsafe(Type resourceType, Action<Resource> initializer);
7395

7496
/// <summary>
7597
/// Read data from a resource
7698
/// </summary>
77-
TResult Read<TResult>(long id, Func<Resource, TResult> accessor);
99+
/// <remarks>
100+
/// The <param name="accessor"></param> action uses the actual resource instance, not wrapped by proxy.
101+
/// As a result, all internal members, including properties and
102+
/// methods not exposed through interfaces, are accessible.
103+
///
104+
/// This API is intended primarily for endpoint controllers that must export or
105+
/// inspect the full internal state of a resource.
106+
///
107+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
108+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
109+
/// </remarks>
110+
TResult ReadUnsafe<TResult>(long id, Func<Resource, TResult> accessor);
78111

79112
/// <summary>
80-
/// Modify the resource.
113+
/// Modify the resource.
81114
/// </summary>
82115
/// <param name="id">Id of the resource</param>
83116
/// <param name="modifier">Modifier delegate, must return <value>true</value> in order to save changes</param>
84-
void Modify(long id, Func<Resource, bool> modifier);
117+
/// <remarks>
118+
/// The <param name="modifier"></param> action uses the actual resource instance, not wrapped by proxy.
119+
/// As a result, all internal members, including properties and
120+
/// methods not exposed through interfaces, are accessible.
121+
///
122+
/// This API is intended primarily for endpoint controllers that must export or
123+
/// inspect the full internal state of a resource.
124+
///
125+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
126+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
127+
/// </remarks>
128+
void ModifyUnsafe(long id, Func<Resource, bool> modifier);
85129

86130
/// <summary>
87131
/// Create and initialize a resource

src/Moryx.AbstractionLayer/Resources/ResourceFacadeExtensions.cs

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,64 +9,92 @@ namespace Moryx.AbstractionLayer.Resources
99
public static class ResourceFacadeExtensions
1010
{
1111
/// <summary>
12-
/// Read data from a resource
12+
/// Read data from a resource by the given resource-proxy
1313
/// </summary>
14-
public static TResult Read<TResult>(this IResourceManagement facade, long resourceId, Func<Resource, TResult> accessor)
14+
/// <param name="facade">Extended facade</param>
15+
/// <param name="proxy">Resource proxy reference</param>
16+
/// <param name="accessor">Accessor delegate for the resource</param>
17+
/// <remarks>
18+
/// The <param name="accessor"></param> action uses the actual resource instance, not wrapped by proxy.
19+
/// As a result, all internal members, including properties and
20+
/// methods not exposed through interfaces, are accessible.
21+
///
22+
/// This API is intended primarily for endpoint controllers that must export or
23+
/// inspect the full internal state of a resource.
24+
///
25+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
26+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
27+
/// </remarks>
28+
public static TResult ReadUnsafe<TResult>(this IResourceManagement facade, IResource proxy, Func<Resource, TResult> accessor)
1529
{
16-
return facade.Read(resourceId, accessor);
30+
return facade.ReadUnsafe(proxy.Id, accessor);
1731
}
1832

1933
/// <summary>
20-
/// Read data from a resource
34+
/// Modify the resource by the given resource-proxy
2135
/// </summary>
22-
public static TResult Read<TResult>(this IResourceManagement facade, IResource proxy, Func<Resource, TResult> accessor)
23-
{
24-
return facade.Read(proxy.Id, accessor);
25-
}
26-
27-
/// <summary>
28-
/// Modify the resource.
29-
/// </summary>
30-
/// <param name="resourceId"></param>
31-
/// <param name="modifier">Modifier delegate, must return <value>true</value> in order to save changes</param>
32-
/// <param name="facade"></param>
33-
public static void Modify(this IResourceManagement facade, long resourceId, Func<Resource, bool> modifier)
34-
{
35-
facade.Modify(resourceId, modifier);
36-
}
37-
38-
/// <summary>
39-
/// Modify the resource.
40-
/// </summary>
41-
/// <param name="proxy"></param>
36+
/// <param name="facade">Extended facade</param>
37+
/// <param name="proxy">Resource proxy reference</param>
4238
/// <param name="modifier">Modifier delegate, must return <value>true</value> in order to save changes</param>
43-
/// <param name="facade"></param>
44-
public static void Modify(this IResourceManagement facade, IResource proxy, Func<Resource, bool> modifier)
39+
/// <remarks>
40+
/// The <param name="modifier"></param> action uses the actual resource instance, not wrapped by proxy.
41+
/// As a result, all internal members, including properties and
42+
/// methods not exposed through interfaces, are accessible.
43+
///
44+
/// This API is intended primarily for endpoint controllers that must export or
45+
/// inspect the full internal state of a resource.
46+
///
47+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
48+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
49+
/// </remarks>
50+
public static void ModifyUnsafe(this IResourceManagement facade, IResource proxy, Func<Resource, bool> modifier)
4551
{
46-
facade.Modify(proxy.Id, modifier);
52+
facade.ModifyUnsafe(proxy.Id, modifier);
4753
}
4854

4955
/// <summary>
50-
/// Modify the resource.
56+
/// Modify the resource.
5157
/// </summary>
52-
/// <param name="proxy"></param>
58+
/// <param name="facade">Extended facade</param>
59+
/// <param name="proxy">Resource proxy reference</param>
5360
/// <param name="modifier">Modifier delegate, must return <value>true</value> in order to save changes</param>
54-
/// <param name="facade"></param>
55-
/// <param name="context"></param>
56-
public static void Modify<TContext>(this IResourceManagement facade, IResource proxy, Func<Resource, TContext, bool> modifier, TContext context)
61+
/// <param name="context">Additional context, used within the <param cref="modifier"/></param>
62+
/// <remarks>
63+
/// The <param name="modifier"></param> action uses the actual resource instance, not wrapped by proxy.
64+
/// As a result, all internal members, including properties and
65+
/// methods not exposed through interfaces, are accessible.
66+
///
67+
/// This API is intended primarily for endpoint controllers that must export or
68+
/// inspect the full internal state of a resource.
69+
///
70+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
71+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
72+
/// </remarks>
73+
public static void ModifyUnsafe<TContext>(this IResourceManagement facade, IResource proxy, Func<Resource, TContext, bool> modifier, TContext context)
5774
{
58-
facade.Modify(proxy.Id, resource => modifier(resource, context));
75+
facade.ModifyUnsafe(proxy.Id, resource => modifier(resource, context));
5976
}
6077

6178
/// <summary>
62-
/// Create a resource with typed initializer
79+
/// Create and initialize a resource with typed initializer
6380
/// </summary>
64-
/// <param name="facade"></param>
65-
/// <param name="initializer"></param>
66-
public static long Create<TResource>(this IResourceManagement facade, Action<TResource> initializer)
81+
/// <remarks>
82+
/// The <param name="initializer"></param> action uses the actual resource instance, not wrapped by proxy.
83+
/// As a result, all internal members, including properties and
84+
/// methods not exposed through interfaces, are accessible.
85+
///
86+
/// This API is intended primarily for endpoint controllers that must export or
87+
/// inspect the full internal state of a resource.
88+
///
89+
/// Because the returned objects are the originals, the API consumer is responsible for keeping and watching the life-cycle.
90+
/// Use with extreme caution. Do not keep the instance in memory for later usage.
91+
/// </remarks>
92+
/// <param name="facade">Extended facade</param>
93+
/// <param name="initializer">Initializer delegate for the resource</param>
94+
public static long CreateUnsafe<TResource>(this IResourceManagement facade, Action<TResource> initializer)
6795
where TResource : Resource
6896
{
69-
return facade.Create(typeof(TResource), r => initializer((TResource)r));
97+
return facade.CreateUnsafe(typeof(TResource), r => initializer((TResource)r));
7098
}
7199
}
72-
}
100+
}

0 commit comments

Comments
 (0)