Interface adjustment due to current standardization activities
Massive refactoring for the better
diff --git a/sdks/dotnet/basyx-core/BaSyx.API/Components/SubmodelServiceProvider.cs b/sdks/dotnet/basyx-core/BaSyx.API/Components/SubmodelServiceProvider.cs
index 02804c1..3ea1ef9 100644
--- a/sdks/dotnet/basyx-core/BaSyx.API/Components/SubmodelServiceProvider.cs
+++ b/sdks/dotnet/basyx-core/BaSyx.API/Components/SubmodelServiceProvider.cs
@@ -10,259 +10,331 @@
 *******************************************************************************/
 using BaSyx.API.AssetAdministrationShell;
 using BaSyx.Models.Core.AssetAdministrationShell.Generics;
-using BaSyx.Models.Core.AssetAdministrationShell.Implementations;
 using BaSyx.Utils.ResultHandling;
 using BaSyx.Utils.Client;
 using System.Collections.Generic;
 using System;
 using Newtonsoft.Json;
-using System.Reflection;
-using System.Linq.Expressions;
 using System.Linq;
 using BaSyx.Models.Connectivity.Descriptors;
 using BaSyx.Models.Core.Common;
-using BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes;
 using BaSyx.Models.Communication;
 using System.Threading.Tasks;
-using BaSyx.Models.Extensions;
+using NLog;
+using System.Threading;
 
 namespace BaSyx.API.Components
 {
+    /// <summary>
+    /// Reference implementation of ISubmodelServiceProvider interface
+    /// </summary>
     public class SubmodelServiceProvider : ISubmodelServiceProvider
     {
-        public ISubmodel Submodel { get; protected set; }
+        private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
+
+        private ISubmodel _submodel;
+
         public ISubmodelDescriptor ServiceDescriptor { get; internal set; }
 
-        private readonly Dictionary<string, Delegate> methodCalledHandler;
-        private readonly Dictionary<string, PropertyHandler> propertyHandler;
+        private readonly Dictionary<string, MethodCalledHandler> methodCalledHandler;
+        private readonly Dictionary<string, SubmodelElementHandler> submodelElementHandler;
         private readonly Dictionary<string, Action<IValue>> updateFunctions;
         private readonly Dictionary<string, EventDelegate> eventDelegates;
         private readonly Dictionary<string, InvocationResponse> invocationResults;
 
         private IMessageClient messageClient;
 
-        private readonly GetPropertyValueHandler GenericPropertyGetHandler = de => { return new ElementValue(de.Value, de.ValueType); };
-        private readonly SetPropertyValueHandler GenericPropertySetHandler = (de, val) => { de.Value = val.Value; };
-
+        /// <summary>
+        /// Constructor for SubmodelServiceProvider
+        /// </summary>
         public SubmodelServiceProvider()
         {
-            methodCalledHandler = new Dictionary<string, Delegate>();
-            propertyHandler = new Dictionary<string, PropertyHandler>();
+            methodCalledHandler = new Dictionary<string, MethodCalledHandler>();
+            submodelElementHandler = new Dictionary<string, SubmodelElementHandler>();
             updateFunctions = new Dictionary<string, Action<IValue>>();
             eventDelegates = new Dictionary<string, EventDelegate>();
             invocationResults = new Dictionary<string, InvocationResponse>();
         }
-
+        /// <summary>
+        /// Contructor for SubmodelServiceProvider with a Submodel object to bind to
+        /// </summary>
+        /// <param name="submodel">Submodel object</param>
         public SubmodelServiceProvider(ISubmodel submodel) : this()
         {
             BindTo(submodel);
         }
+        /// <summary>
+        /// Contructor for SubmodelServiceProvider with a Submodel object to bind to and a SubmodelDescriptor as ServiceDescriptor
+        /// </summary>
+        /// <param name="submodel">Submodel object</param>
+        /// <param name="submodelDescriptor">SubmodelDescriptor object</param>
         public SubmodelServiceProvider(ISubmodel submodel, ISubmodelDescriptor submodelDescriptor) : this()
         {
-            Submodel = submodel;
+            _submodel = submodel;
             ServiceDescriptor = submodelDescriptor;
         }
 
-        public void BindTo(ISubmodel element)
+        /// <summary>
+        /// Bind this SubmodelServiceProvider to a specific Submodel
+        /// </summary>
+        /// <param name="submodel">Submodel object</param>
+        public void BindTo(ISubmodel submodel)
         {
-            Submodel = element;
-            ServiceDescriptor = new SubmodelDescriptor(element, null);
+            _submodel = submodel;
+            ServiceDescriptor = new SubmodelDescriptor(submodel, null);
         }
+
+        /// <summary>
+        /// Returns the model binding of this SubmodelServiceProvider
+        /// </summary>
+        /// <returns>Submodel object</returns>
         public ISubmodel GetBinding()
         {
-            return Submodel;
+            return _submodel;
         }
 
-        public void UseInMemoryPropertyHandler()
+        public void UseInMemorySubmodelElementHandler()
         {
-            if(Submodel.Properties?.Count() > 0)
-                foreach (var property in Submodel.Properties)
+            UseInMemorySubmodelElementHandlerInternal(_submodel.SubmodelElements);
+        }
+        private void UseInMemorySubmodelElementHandlerInternal(IElementContainer<ISubmodelElement> submodelElements)
+        {
+            if (submodelElements.HasChildren())
+            {
+                foreach (var child in submodelElements.Children)
                 {
-                    RegisterPropertyHandler(property.IdShort,
-                        new PropertyHandler(property.Get ?? GenericPropertyGetHandler, property.Set ?? GenericPropertySetHandler));
+                    UseInMemorySubmodelElementHandlerInternal(child);
                 }
+            }
+            if(submodelElements.Value != null)
+            {
+                if (submodelElements.Value.ModelType != ModelType.Operation)
+                    RegisterSubmodelElementHandler(submodelElements.Path, new SubmodelElementHandler(submodelElements.Value.Get, submodelElements.Value.Set));                
+            }
         }
 
-        public void UsePropertyHandler(PropertyHandler propertyHandler)
+        /// <summary>
+        /// Use as specific SubmodelElementHandler for all SubmodelElements
+        /// </summary>
+        /// <param name="elementHandler">SubmodelElementHandler</param>
+        public void UseSubmodelElementHandler(SubmodelElementHandler elementHandler)
         {
-            if (Submodel.Properties?.Count() > 0)
-                foreach (var property in Submodel.Properties)
-                    RegisterPropertyHandler(property.IdShort, propertyHandler);
+            UseSubmodelElementHandlerInternal(_submodel.SubmodelElements, elementHandler, null);
+        }
+        /// <summary>
+        /// Use a specific SubmodelElementHandler for all SubmodelElements of a specific ModelType (e.g. Property) except Operations
+        /// </summary>
+        /// <param name="elementHandler">SubmodelElementHandler</param>
+        /// <param name="modelType">ModelType</param>
+        public void UseSubmodelElementHandlerForModelType(SubmodelElementHandler elementHandler, ModelType modelType)
+        {
+            UseSubmodelElementHandlerInternal(_submodel.SubmodelElements, elementHandler, modelType);
         }
 
+        private void UseSubmodelElementHandlerInternal(IElementContainer<ISubmodelElement> submodelElements, SubmodelElementHandler elementHandler, ModelType modelType = null)
+        {
+            if (submodelElements.HasChildren())
+            {
+                foreach (var child in submodelElements.Children)
+                {
+                    UseSubmodelElementHandlerInternal(child, elementHandler, modelType);
+                }
+            }
+            if (submodelElements.Value != null)
+            {
+                if (modelType == null)
+                    RegisterSubmodelElementHandler(submodelElements.Path, elementHandler);
+                else if (submodelElements.Value.ModelType == modelType)
+                    RegisterSubmodelElementHandler(submodelElements.Path, elementHandler);
+                else
+                    return;
+            }
+        }
+        /// <summary>
+        /// Use a specific MethodCalledHandler for all Operations
+        /// </summary>
+        /// <param name="methodCalledHandler"></param>
         public void UseOperationHandler(MethodCalledHandler methodCalledHandler)
         {
-            if (Submodel.Operations?.Count() > 0)
-                foreach (var operation in Submodel.Operations)
-                    RegisterMethodCalledHandler(operation.IdShort, methodCalledHandler);
+            UseOperationHandlerInternal(_submodel.SubmodelElements, methodCalledHandler);
         }
 
-        public IResult<IEvent> CreateEvent(IEvent eventable)
+        private void UseOperationHandlerInternal(IElementContainer<ISubmodelElement> submodelElements, MethodCalledHandler methodCalledHandler)
         {
-            if (Submodel == null)
-                return new Result<IEvent>(false, new NotFoundMessage("Submodel"));
-
-            return Submodel.SubmodelElements.Create(eventable);
-        }
-
-        public IResult<IOperation> CreateOperation(IOperation operation)
-        {
-            if (Submodel == null)
-                return new Result<IOperation>(false, new NotFoundMessage("Submodel"));
-
-            return Submodel.SubmodelElements.Create(operation);
-        }
-
-        public IResult<IProperty> CreateProperty(IProperty property)
-        {
-            if (Submodel == null)
-                return new Result<IProperty>(false, new NotFoundMessage("Submodel"));
-
-            RegisterPropertyHandler(property.IdShort, 
-                new PropertyHandler(property.Get ?? GenericPropertyGetHandler, property.Set ?? GenericPropertySetHandler));
-
-            return Submodel.SubmodelElements.Create(property);
-        }
-
-        public IResult DeleteEvent(string eventId)
-        {
-            if (Submodel == null)
-                return new Result(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Events == null)
-                return new Result(false, new NotFoundMessage(eventId));
-            return Submodel.SubmodelElements.Delete(eventId);
-        }
-
-        public IResult DeleteOperation(string operationId)
-        {
-            if (Submodel == null)
-                return new Result(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Operations == null)
-                return new Result(false, new NotFoundMessage(operationId));
-            return Submodel.SubmodelElements.Delete(operationId);
-        }
-
-        public IResult DeleteProperty(string propertyId)
-        {
-            if (Submodel == null)
-                return new Result(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Properties == null)
-                return new Result(false, new NotFoundMessage(propertyId));
-
-            if (propertyHandler.ContainsKey(propertyId))
-                propertyHandler.Remove(propertyId);
-
-            return Submodel.SubmodelElements.Delete(propertyId);
-        }
-
-        public MethodCalledHandler RetrieveMethodCalledHandler(string operationId)
-        {
-            if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
-                return (MethodCalledHandler)handler;
+            if (submodelElements.HasChildren())
+            {
+                foreach (var child in submodelElements.Children)
+                {
+                    UseOperationHandlerInternal(child, methodCalledHandler);
+                }
+            }
             else
-                return null;
+            {
+                if (submodelElements.Value is IOperation)
+                    RegisterMethodCalledHandler(submodelElements.Path, methodCalledHandler);
+                else
+                    return;
+            }
         }
-
-        public Delegate RetrieveMethodDelegate(string operationId)
+        
+        public MethodCalledHandler RetrieveMethodCalledHandler(string pathToOperation)
         {
-            if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
+            if (methodCalledHandler.TryGetValue(pathToOperation, out MethodCalledHandler handler))
                 return handler;
             else
                 return null;
         }
-
-        public PropertyHandler RetrievePropertyHandler(string propertyId)
+       
+        public SubmodelElementHandler RetrieveSubmodelElementHandler(string pathToElement)
         {
-            if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler))
-                return handler;
+            if (submodelElementHandler.TryGetValue(pathToElement, out SubmodelElementHandler elementHandler))
+                return elementHandler;
             else
                 return null;
         }
-
-        public void RegisterPropertyHandler(string propertyId, PropertyHandler handler)
+      
+        public void RegisterSubmodelElementHandler(string pathToElement, SubmodelElementHandler elementHandler)
         {
-            if (!propertyHandler.ContainsKey(propertyId))
-                propertyHandler.Add(propertyId, handler);
+            if (!submodelElementHandler.ContainsKey(pathToElement))
+                submodelElementHandler.Add(pathToElement, elementHandler);
             else
-                propertyHandler[propertyId] = handler;
+                submodelElementHandler[pathToElement] = elementHandler;
         }
-
-        public void RegisterMethodCalledHandler(string operationId, MethodCalledHandler handler)
+        
+        public void RegisterMethodCalledHandler(string pathToOperation, MethodCalledHandler handler)
         {
-            if (!methodCalledHandler.ContainsKey(operationId))
-                methodCalledHandler.Add(operationId, handler);
+            if (!methodCalledHandler.ContainsKey(pathToOperation))
+                methodCalledHandler.Add(pathToOperation, handler);
             else
-                methodCalledHandler[operationId] = handler;
+                methodCalledHandler[pathToOperation] = handler;
         }
-
-        public void RegisterMethodCalledHandler(string operationId, Delegate handler)
+          
+        public void RegisterEventDelegate(string pathToEvent, EventDelegate eventDelegate)
         {
-            if (!methodCalledHandler.ContainsKey(operationId))
-                methodCalledHandler.Add(operationId, handler);
+            if (!eventDelegates.ContainsKey(pathToEvent))
+                eventDelegates.Add(pathToEvent, eventDelegate);
             else
-                methodCalledHandler[operationId] = handler;
+                eventDelegates[pathToEvent] = eventDelegate;
         }
 
-        public void RegisterEventDelegate(string eventId, EventDelegate eventDelegate)
+        public IResult<InvocationResponse> InvokeOperation(string pathToOperation, InvocationRequest invocationRequest)
         {
-            if (!eventDelegates.ContainsKey(eventId))
-                eventDelegates.Add(eventId, eventDelegate);
-            else
-                eventDelegates[eventId] = eventDelegate;
+            if (_submodel == null)
+                return new Result<InvocationResponse>(false, new NotFoundMessage("Submodel"));
+
+            var operation_Retrieved = _submodel.SubmodelElements.Retrieve<IOperation>(pathToOperation);
+            if (operation_Retrieved.Success && operation_Retrieved.Entity != null)
+            {
+                MethodCalledHandler methodHandler;
+                if (operation_Retrieved.Entity.OnMethodCalled != null)
+                    methodHandler = operation_Retrieved.Entity.OnMethodCalled;
+                else if (methodCalledHandler.TryGetValue(pathToOperation, out MethodCalledHandler handler))
+                    methodHandler = handler;
+                else
+                    return new Result<InvocationResponse>(false, new NotFoundMessage($"MethodHandler for {pathToOperation}"));
+
+                InvocationResponse invocationResponse = new InvocationResponse(invocationRequest.RequestId);
+                invocationResponse.InOutputArguments = invocationRequest.InOutputArguments;
+
+                using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
+                {
+                    Task<OperationResult> runner = Task.Run(async () =>
+                    {
+                        try
+                        {
+                            invocationResponse.ExecutionState = ExecutionState.Running;
+                            var result = await methodHandler.Invoke(operation_Retrieved.Entity, invocationRequest.InputArguments, invocationResponse.InOutputArguments, invocationResponse.OutputArguments, cancellationTokenSource.Token);
+                            invocationResponse.ExecutionState = ExecutionState.Completed;
+                            return result;
+                        }
+                        catch (Exception e)
+                        {
+                            invocationResponse.ExecutionState = ExecutionState.Failed;
+                            return new OperationResult(e);
+                        }
+
+                    }, cancellationTokenSource.Token);
+
+                    if (Task.WhenAny(runner, Task.Delay(invocationRequest.Timeout.Value, cancellationTokenSource.Token)).Result == runner)
+                    {
+                        cancellationTokenSource.Cancel();
+                        invocationResponse.OperationResult = runner.Result;
+                        return new Result<InvocationResponse>(true, invocationResponse);
+                    }
+                    else
+                    {
+                        cancellationTokenSource.Cancel();
+                        invocationResponse.OperationResult = new OperationResult(false, new TimeoutMessage());
+                        invocationResponse.ExecutionState = ExecutionState.Timeout;
+                        return new Result<InvocationResponse>(false, invocationResponse);
+                    }
+                }
+            }
+            return new Result<InvocationResponse>(operation_Retrieved);
         }
 
-        public void RegisterMethodCalledHandler(string operationId, MethodInfo methodInfo, object target)
+        public IResult<CallbackResponse> InvokeOperationAsync(string pathToOperation, InvocationRequest invocationRequest)
         {
-            var parameters = from parameter in methodInfo.GetParameters() select parameter.ParameterType;
-            Delegate del = methodInfo.CreateDelegate(Expression.GetDelegateType(parameters.Concat(new[] { methodInfo.ReturnType }).ToArray()), target);
-            RegisterMethodCalledHandler(operationId, del);
-        }
-
-        public IResult<CallbackResponse> InvokeOperationAsync(string operationId, InvocationRequest invocationRequest)
-        {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result<CallbackResponse>(false, new NotFoundMessage("Submodel"));
             if (invocationRequest == null)
                 return new Result<CallbackResponse>(new ArgumentNullException(nameof(invocationRequest)));
 
-            var operation_Retrieved = RetrieveOperation(operationId);
+            var operation_Retrieved = _submodel.SubmodelElements.Retrieve<IOperation>(pathToOperation);
             if (operation_Retrieved.Success && operation_Retrieved.Entity != null)
             {
-                Delegate methodDelegate;
+                MethodCalledHandler methodHandler;
                 if (operation_Retrieved.Entity.OnMethodCalled != null)
-                    methodDelegate = operation_Retrieved.Entity.OnMethodCalled;
-                else if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
-                    methodDelegate = handler;
+                    methodHandler = operation_Retrieved.Entity.OnMethodCalled;
+                else if (methodCalledHandler.TryGetValue(pathToOperation, out MethodCalledHandler handler))
+                    methodHandler = handler;
                 else
-                    return new Result<CallbackResponse>(false, new NotFoundMessage($"MethodHandler for {operationId}"));
+                    return new Result<CallbackResponse>(false, new NotFoundMessage($"MethodHandler for {pathToOperation}"));
 
-                var invocationTask = Task.Run(() =>
+                Task invocationTask = Task.Run(async() =>
                 {
                     InvocationResponse invocationResponse = new InvocationResponse(invocationRequest.RequestId);
-                    SetInvocationResult(operationId, invocationRequest.RequestId, ref invocationResponse);
+                    invocationResponse.InOutputArguments = invocationRequest.InOutputArguments;
+                    SetInvocationResult(pathToOperation, invocationRequest.RequestId, ref invocationResponse);
 
-                    try
+                    using (var cancellationTokenSource = new CancellationTokenSource())
                     {
-                        invocationResponse.ExecutionState = ExecutionState.Running;
-                        Task<OperationResult> taskResult = (Task<OperationResult>)methodDelegate.DynamicInvoke(operation_Retrieved.Entity, invocationRequest.InputArguments, invocationResponse.OutputArguments);
-                        invocationResponse.OperationResult = taskResult.Result;
-                        invocationResponse.ExecutionState = ExecutionState.Completed;
-                    }
-                    catch (Exception e)
-                    {
-                        invocationResponse.ExecutionState = ExecutionState.Failed;
-                        invocationResponse.OperationResult = new OperationResult(e);
+                        Task<OperationResult> runner = Task.Run(async () =>
+                        {
+                            try
+                            {
+                                invocationResponse.ExecutionState = ExecutionState.Running;
+                                var result = await methodHandler.Invoke(operation_Retrieved.Entity, invocationRequest.InputArguments, invocationResponse.InOutputArguments, invocationResponse.OutputArguments, cancellationTokenSource.Token);
+                                invocationResponse.ExecutionState = ExecutionState.Completed;
+                                return result;
+                            }
+                            catch (Exception e)
+                            {
+                                invocationResponse.ExecutionState = ExecutionState.Failed;
+                                return new OperationResult(e);
+                            }
+                        }, cancellationTokenSource.Token);
+
+                        if (await Task.WhenAny(runner, Task.Delay(invocationRequest.Timeout.Value, cancellationTokenSource.Token)) == runner)
+                        {
+                            cancellationTokenSource.Cancel();
+                            invocationResponse.OperationResult = runner.Result;
+                        }
+                        else
+                        {
+                            cancellationTokenSource.Cancel();
+                            invocationResponse.OperationResult = new OperationResult(false, new TimeoutMessage());
+                            invocationResponse.ExecutionState = ExecutionState.Timeout;
+                        }
                     }
                 });
+         
                 string endpoint = ServiceDescriptor?.Endpoints?.FirstOrDefault()?.Address;
                 CallbackResponse callbackResponse = new CallbackResponse(invocationRequest.RequestId);
                 if (string.IsNullOrEmpty(endpoint))
-                    callbackResponse.CallbackUrl = new Uri($"/operations/{operationId}/invocationList/{invocationRequest.RequestId}", UriKind.Relative);
+                    callbackResponse.CallbackUrl = new Uri($"/submodelElements/{pathToOperation}/invocationList/{invocationRequest.RequestId}", UriKind.Relative);
                 else
-                    callbackResponse.CallbackUrl = new Uri($"{endpoint}/operations/{operationId}/invocationList/{invocationRequest.RequestId}", UriKind.Absolute);
+                    callbackResponse.CallbackUrl = new Uri($"{endpoint}/submodelElements/{pathToOperation}/invocationList/{invocationRequest.RequestId}", UriKind.Absolute);
                 return new Result<CallbackResponse>(true, callbackResponse);
             }
             return new Result<CallbackResponse>(operation_Retrieved);
@@ -280,10 +352,10 @@
                 invocationResults.Add(key, invocationResponse);
             }
         }
-
-        public IResult<InvocationResponse> GetInvocationResult(string operationId, string requestId)
+      
+        public IResult<InvocationResponse> GetInvocationResult(string pathToOperation, string requestId)
         {
-            string key = string.Join("_", operationId, requestId);
+            string key = string.Join("_", pathToOperation, requestId);
             if (invocationResults.ContainsKey(key))
             {
                 return new Result<InvocationResponse>(true, invocationResults[key]);
@@ -292,42 +364,8 @@
             {
                return new Result<InvocationResponse>(false, new NotFoundMessage($"Request with id {requestId}"));
             }
-        }
-
-
-        public IResult<InvocationResponse> InvokeOperation(string operationId, InvocationRequest invocationRequest)
-        {
-            if (Submodel == null)
-                return new Result<InvocationResponse>(false, new NotFoundMessage("Submodel"));
-
-            var operation_Retrieved = RetrieveOperation(operationId);
-            if (operation_Retrieved.Success && operation_Retrieved.Entity != null)
-            {
-                Delegate methodDelegate;
-                if (operation_Retrieved.Entity.OnMethodCalled != null)
-                    methodDelegate = operation_Retrieved.Entity.OnMethodCalled;
-                else if (methodCalledHandler.TryGetValue(operationId, out Delegate handler))
-                    methodDelegate = handler;
-                else
-                    return new Result<InvocationResponse>(false, new NotFoundMessage($"MethodHandler for {operationId}"));
-                try
-                {
-                    InvocationResponse invocationResponse = new InvocationResponse(invocationRequest.RequestId);
-                    invocationResponse.ExecutionState = ExecutionState.Running;
-                    Task<OperationResult> taskResult = (Task<OperationResult>)methodDelegate.DynamicInvoke(operation_Retrieved.Entity, invocationRequest.InputArguments, invocationResponse.OutputArguments);
-                    invocationResponse.OperationResult = taskResult.Result;
-                    invocationResponse.ExecutionState = ExecutionState.Completed;
-
-                    return new Result<InvocationResponse>(true, invocationResponse);
-                }
-                catch (Exception e)
-                {
-                    return new Result<InvocationResponse>(e);
-                }
-            }
-            return new Result<InvocationResponse>(operation_Retrieved);
-        }
-
+        }              
+       
         public IResult ThrowEvent(IPublishableEvent publishableEvent, string topic = "/", Action<IMessagePublishedEventArgs> MessagePublished = null, byte qosLevel = 2, bool retain = false)
         {
             if (messageClient == null || !messageClient.IsConnected)
@@ -343,229 +381,117 @@
             return messageClient.Publish(topic, message, MessagePublished, qosLevel, retain);
         }
 
-        public IResult<IEvent> RetrieveEvent(string eventId)
-        {
-            if (Submodel == null)
-                return new Result<IEvent>(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Events == null)
-                return new Result<IEvent>(false, new NotFoundMessage(eventId));
-            return Submodel.SubmodelElements.Retrieve<IEvent>(eventId);
-        }
-
-        public IResult<IElementContainer<IEvent>> RetrieveEvents()
-        {
-            if (Submodel == null)
-                return new Result<ElementContainer<IEvent>>(false, new NotFoundMessage("Submodel"));
-
-            if(Submodel.Events == null)
-                return new Result<ElementContainer<IEvent>>(false, new NotFoundMessage("Events"));
-            return Submodel.SubmodelElements.RetrieveAll<IEvent>();
-        }
-
-        public IResult<IOperation> RetrieveOperation(string operationId)
-        {
-            if (Submodel == null)
-                return new Result<IOperation>(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Operations == null)
-                return new Result<IOperation>(false, new NotFoundMessage(operationId));
-            return Submodel.SubmodelElements.Retrieve<IOperation>(operationId);
-        }
-
-        public IResult<IElementContainer<IOperation>> RetrieveOperations()
-        {
-            if (Submodel == null)
-                return new Result<ElementContainer<IOperation>>(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Operations == null)
-                return new Result<ElementContainer<IOperation>>(false, new NotFoundMessage("Operations"));
-            return Submodel.SubmodelElements.RetrieveAll<IOperation>();
-        }
-
-        public IResult<IElementContainer<IProperty>> RetrieveProperties()
-        {
-            if (Submodel == null)
-                return new Result<ElementContainer<IProperty>>(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Properties == null)
-                return new Result<ElementContainer<IProperty>>(false, new NotFoundMessage("Properties"));
-            return Submodel.SubmodelElements.RetrieveAll<IProperty>();
-        }
-
-        public IResult<IProperty> RetrieveProperty(string propertyId)
-        {
-            if (Submodel == null)
-                return new Result<IProperty>(false, new NotFoundMessage("Submodel"));
-
-            if (Submodel.Properties == null)
-                return new Result<IProperty>(false, new NotFoundMessage(propertyId));
-            return Submodel.SubmodelElements.Retrieve<IProperty>(propertyId);
-        }
-
-        public IResult<IValue> RetrievePropertyValue(string propertyId)
-        {
-            if (Submodel == null)
-                return new Result<IValue>(false, new NotFoundMessage("Submodel"));
-
-            if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler) && handler.GetHandler != null)
-            {
-                var property = RetrieveProperty(propertyId);
-                if(property.Success && property.Entity != null)
-                    return new Result<IValue>(true, handler.GetHandler.Invoke(property.Entity));
-                else
-                    return new Result<IValue>(false, new Message(MessageType.Error, "property not found"));
-            }
-            else
-                return new Result<IValue>(false, new Message(MessageType.Error, "propertyHandler or GetHandler not found"));
-        }
-
-
-        public IResult UpdatePropertyValue(string propertyId, IValue value)
-        {
-            if (Submodel == null)
-                return new Result(false, new NotFoundMessage("Submodel"));
-
-            if (propertyHandler.TryGetValue(propertyId, out PropertyHandler handler) && handler.SetHandler != null)
-            {
-                var property = RetrieveProperty(propertyId);
-                if (property.Success && property.Entity != null)
-                {
-                    handler.SetHandler.Invoke(property.Entity, value);
-                    return new Result(true);
-                }
-                else
-                    return new Result<IValue>(false, new Message(MessageType.Error, "property not found"));
-            }
-            else
-                return new Result<IValue>(false, new Message(MessageType.Error, "propertyHandler or SetHandler not found"));
-        }
-
+       
         public virtual void ConfigureEventHandler(IMessageClient messageClient)
         {
             this.messageClient = messageClient;
         }
-
-        public virtual void SubscribeUpdates(string propertyId, Action<IValue> updateFunction)
+       
+        public virtual void SubscribeUpdates(string pathToSubmodelElement, Action<IValue> updateFunction)
         {
-            if (!updateFunctions.ContainsKey(propertyId))
-                updateFunctions.Add(propertyId, updateFunction);
+            if (!updateFunctions.ContainsKey(pathToSubmodelElement))
+                updateFunctions.Add(pathToSubmodelElement, updateFunction);
             else
-                updateFunctions[propertyId] = updateFunction;
+                updateFunctions[pathToSubmodelElement] = updateFunction;
         }
-
-        public virtual void PublishUpdate(string propertyId, IValue value)
+       
+        public virtual void PublishUpdate(string pathToSubmodelElement, IValue value)
         {
-            if (updateFunctions.TryGetValue(propertyId, out Action<IValue> updateFunction))
+            if (updateFunctions.TryGetValue(pathToSubmodelElement, out Action<IValue> updateFunction))
                 updateFunction.Invoke(value);
 
         }
 
         public IResult<ISubmodel> RetrieveSubmodel()
         {
-            var submodel = GetBinding();
-            return new Result<ISubmodel>(submodel != null, submodel);
+            return new Result<ISubmodel>(_submodel != null, _submodel);
         }
 
-        public IResult<ISubmodelElement> CreateSubmodelElement(ISubmodelElement submodelElement)
+        public IResult<ISubmodelElement> CreateSubmodelElement(string pathToSubmodelElement, ISubmodelElement submodelElement)
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result<ISubmodelElement>(false, new NotFoundMessage("Submodel"));
 
-            return Submodel.SubmodelElements.Create(submodelElement);
+            return _submodel.SubmodelElements.Create(submodelElement);
         }
 
         public IResult<IElementContainer<ISubmodelElement>> RetrieveSubmodelElements()
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result<ElementContainer<ISubmodelElement>>(false, new NotFoundMessage("Submodel"));
 
-            if (Submodel.SubmodelElements == null)
+            if (_submodel.SubmodelElements == null)
                 return new Result<ElementContainer<ISubmodelElement>>(false, new NotFoundMessage("SubmodelElements"));
-            return Submodel.SubmodelElements.RetrieveAll();
+            return _submodel.SubmodelElements.RetrieveAll();
         }
 
         public IResult<ISubmodelElement> RetrieveSubmodelElement(string submodelElementId)
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result<ISubmodelElement>(false, new NotFoundMessage("Submodel"));
 
-            if (Submodel.SubmodelElements == null)
+            if (_submodel.SubmodelElements == null)
                 return new Result<ISubmodelElement>(false, new NotFoundMessage(submodelElementId));
 
-            IResult<ISubmodelElement> result;
-            if(submodelElementId.Contains("/"))
-            {
-                string[] smeIds = submodelElementId.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
-                IResult<ISubmodelElement> firstElement = Submodel.SubmodelElements.Retrieve(smeIds[0]);
-                result = RetrieveSubordinateElement(firstElement, smeIds.Skip(1));
-            }
-            else
-            {
-                result = Submodel.SubmodelElements.Retrieve(submodelElementId);
-            }
-            return result;
+            return _submodel.SubmodelElements.Retrieve(submodelElementId);
         }
-
-        private IResult<ISubmodelElement> RetrieveSubordinateElement(IResult<ISubmodelElement> smElement, IEnumerable<string> idShorts)
-        {
-            if(smElement.Success && smElement.Entity != null)
-            {
-                if(smElement.Entity.ModelType == ModelType.SubmodelElementCollection)
-                {
-                    ISubmodelElementCollection smeCollection = smElement.Entity.Cast<ISubmodelElementCollection>();
-                    if(idShorts?.Count() > 0 && smeCollection.Value?.Count > 0)
-                    {
-                        IResult<ISubmodelElement> nextElement = smeCollection.Value.Retrieve(idShorts.First());
-                        if (idShorts.Count() > 1)
-                            return RetrieveSubordinateElement(nextElement, idShorts.Skip(1));
-                        else
-                            return nextElement;
-                    }
-                }
-                else
-                {
-                    if (idShorts.Count() > 0)
-                        return new Result<ISubmodelElement>(false, new NotFoundMessage(string.Join("/", idShorts)));
-                }
-            }
-            return smElement;
-        }
-
         public IResult<IValue> RetrieveSubmodelElementValue(string submodelElementId)
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result<IValue>(false, new NotFoundMessage("Submodel"));
 
-            if (Submodel.SubmodelElements == null)
-                return new Result<IValue>(false, new NotFoundMessage(submodelElementId));
-
-            return new Result<IValue>(true, 
-                new ElementValue(
-                    (Submodel.SubmodelElements[submodelElementId] as dynamic).Value, 
-                    (Submodel.SubmodelElements[submodelElementId] as dynamic).ValueType as DataType));
+            if (submodelElementHandler.TryGetValue(submodelElementId, out SubmodelElementHandler elementHandler) && elementHandler.GetValueHandler != null)
+            {
+                var submodelElement = _submodel.SubmodelElements.Retrieve<ISubmodelElement>(submodelElementId);
+                if (submodelElement.Success && submodelElement.Entity != null)
+                    return new Result<IValue>(true, elementHandler.GetValueHandler.Invoke(submodelElement.Entity));
+                else
+                    return new Result<IValue>(false, new Message(MessageType.Error, "SubmodelElement not found"));
+            }
+            else
+                return new Result<IValue>(false, new Message(MessageType.Error, "SubmodelElementHandler not found"));
         }
 
         public IResult UpdateSubmodelElement(string submodelElementId, ISubmodelElement submodelElement)
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result(false, new NotFoundMessage("Submodel"));
 
-            if (Submodel.SubmodelElements == null)
+            if (_submodel.SubmodelElements == null)
                 return new Result(false, new NotFoundMessage(submodelElementId));
 
-            return Submodel.SubmodelElements.Update(submodelElementId, submodelElement);
+            return _submodel.SubmodelElements.Update(submodelElementId, submodelElement);
+        }
+
+        public IResult UpdateSubmodelElementValue(string submodelElementId, IValue value)
+        {
+            if (_submodel == null)
+                return new Result(false, new NotFoundMessage("Submodel"));
+
+            if (submodelElementHandler.TryGetValue(submodelElementId, out SubmodelElementHandler elementHandler) && elementHandler.SetValueHandler != null)
+            {
+                var submodelElement = _submodel.SubmodelElements.Retrieve<ISubmodelElement>(submodelElementId);
+                if (submodelElement.Success && submodelElement.Entity != null)
+                {
+                    elementHandler.SetValueHandler.Invoke(submodelElement.Entity, value);
+                    return new Result(true);
+                }
+                else
+                    return new Result<IValue>(false, new Message(MessageType.Error, "property not found"));
+            }
+            else
+                return new Result<IValue>(false, new Message(MessageType.Error, "SubmodelElementHandler not found"));
         }
 
         public IResult DeleteSubmodelElement(string submodelElementId)
         {
-            if (Submodel == null)
+            if (_submodel == null)
                 return new Result(false, new NotFoundMessage("Submodel"));
 
-            if (Submodel.SubmodelElements == null)
+            if (_submodel.SubmodelElements == null)
                 return new Result(false, new NotFoundMessage(submodelElementId));
 
-            return Submodel.SubmodelElements.Delete(submodelElementId);
+            return _submodel.SubmodelElements.Delete(submodelElementId);
         }        
     }
 }