uid |
---|
HowToCreateAResource |
This tutorial shows how a Resource should be implemented. Take a look here, if you are not firm with the concept of a Resource
. This tutorial describes how a basic Resource
is created. Besides the basic Resource
that this tutorial tackels, other more specialized types include Public resources, Driver resources or Interaction resources.
A resource has this basic solution structure which can be extended for your needs:
-Moryx.Resource.ExampleResource
|-IExampleResource.cs
|-ExampleResource.cs
The interface IExampleResource
is optional for a resource and probably better located in a shared project between resources and modules. The implementation of this interface is done with the ExampleResource
class.
This interface is simply derived from IResource. No further definitions are needed.
using Moryx.AbstractionLayer.Resources;
namespace Moryx.Resources.Samples.DriverTutorial
{
public interface IExampleResource : IResource
{
}
}
Now implement IExampleResource
:
using System.ComponentModel;
using System.Runtime.Serialization;
using Moryx.AbstractionLayer.Resources;
using Moryx.Serialization;
namespace Moryx.Resources.Samples.DriverTutorial
{
[ResourceRegistration]
[DisplayName("Example Resource"), Description("An example resource")]
public class ExampleResource : Resource, IExampleResource
{
[DataMember, EntrySerialize]
public string AStringValue { get; set; }
[DataMember, EntrySerialize]
public int AnIntValue { get; set; }
public string ANonEntrySerializeMember { get; set; }
[EntrySerialize, DisplayName("Square"), Description("Just multiplies given value with itself")]
public int Square(int value)
{
return value * value;
}
}
}
The implementation of the ExampleResource
derives from the Resource base class. It also implements the IResource
interface. This is enough to use your resource definition within MORYX. If your resource relies on dependency injection like logging it is important to add the ResourceRegistration attribute. MORYX can now identify this class as a resource. Properties or methods with the Attribute EntrySerialize
will be shown in the UI. The Attribute DataMember
marks all properties saved in the database. Additional attributes like DisplayName
and Description
are used within the Resource UI.
Resources can reference other resources. When for example a cell communicates with a PLC via a Driver, the Driver has to be referenced in the Cell. Every Resource has the References Children
and Parent
by default. In order to overwrite
References use the attribute ReferenceOverride
. New References can be added using the attribute ResourceReference
. For the different ResourceRelationTypes take a look here.
[ResourceRegistration]
public class ExampleCell : PublicResource
{
[ResourceReference(ResourceRelationType.Driver)]
public IMessageDriver<object> Driver {get;set;}
[ReferenceOverride(nameof(Children))]
public IReferences<IMessageChannel> Channels {get;set;}
}
If you want to use the new resource from a custom module, you need to request the resource from the ResourceManagement. Inject the ResourceManagement
into the ModuleController
and pass the object to the inner container of your custom module.
[ServerModule(ModuleName)]
public class ModuleController : ServerModuleBase<ModuleConfig>
{
//Let the component be injected from the external container
[RequiredModuleApi(IsOptional = false, IsStartDependency = true)]
public IResourceManagement ResourceManagement { get; set; }
public override string Name
{
///
}
#region state transition
protected override void OnInitialize()
{
//pass the component to the inner container
Container.SetInstance(ResourceManagement);
ResourceManagement.CapabilitiesChanged += ExampleResourceCapabilityChanged;
}
protected override void OnStart()
{
///
}
protected override void OnStop()
{
///
}
#endregion
}
If it is nesessary to react when a capability has changed, is it possible to attach to the CapabilityChanged event:
private void ExampleResourceCapabilityChanged(object sender, ICapabilities newCapabilities)
{
var id = ((IResource)sender).Id;
// Do something
}