public async Task AddToNameCache(string deviceId)
        {
            var device = await this.GetDeviceAsync(deviceId);

            var twin = device.Twin;

            await _nameCacheLogic.AddNameAsync(nameof(device.Twin.DeviceId));

            await _nameCacheLogic.AddShortNamesAsync(
                NameCacheEntityType.Tag,
                twin.Tags
                .AsEnumerableFlatten()
                .Select(pair => pair.Key));

            await _nameCacheLogic.AddShortNamesAsync(
                NameCacheEntityType.DesiredProperty,
                twin.Properties.Desired
                .AsEnumerableFlatten()
                .Select(pair => pair.Key));

            await _nameCacheLogic.AddShortNamesAsync(
                NameCacheEntityType.ReportedProperty,
                twin.Properties.Reported
                .AsEnumerableFlatten()
                .Select(pair => pair.Key)
                .Where(name => !SupportedMethodsHelper.IsSupportedMethodProperty(name)));

            foreach (var command in device.Commands.Where(c => c.DeliveryType == DeliveryType.Method))
            {
                await _nameCacheLogic.AddMethodAsync(command);
            }
        }
        private void UpdateNameCache(IEnumerable <Shared.Twin> twins)
        {
            // Reminder: None of the tasks updating the namecache need to be waited for completed

            var tags    = twins.GetNameList(twin => twin.Tags);
            var tagTask = _nameCacheLogic.AddShortNamesAsync(NameCacheEntityType.Tag, tags);

            var desiredProperties   = twins.GetNameList(twin => twin.Properties.Desired);
            var desiredPropertyTask = _nameCacheLogic.AddShortNamesAsync(NameCacheEntityType.DesiredProperty, desiredProperties);

            var reportedProperties = twins.GetNameList(twin => twin.Properties.Reported)
                                     .Where(name => !SupportedMethodsHelper.IsSupportedMethodProperty(name));
            var reportedPropertyTask = _nameCacheLogic.AddShortNamesAsync(NameCacheEntityType.ReportedProperty, reportedProperties);

            // No need to update Method here, since it will not change during device running
        }
        // Copy values from twin to view model
        // All of the tags, desired and reported properties will be copy to view model. While the reported properties will be marked as non-editable
        //
        // Reminder: Only DeviceModel.Twin and cloud service configuration 'iotHub.HostName' will be read. . DeviceProperties and other properties of class DeviceModel will not be touched
        public override IEnumerable <DevicePropertyValueModel> ExtractDevicePropertyValuesModels(
            DeviceModel device)
        {
            string hostNameValue;
            IEnumerable <DevicePropertyValueModel> propValModels;

            if (device == null)
            {
                throw new ArgumentNullException("device");
            }

            var tags = device.Twin.Tags.AsEnumerableFlatten().OrderBy(pair => pair.Key).Select(pair => new DevicePropertyValueModel
            {
                DisplayOrder = 1,
                IsEditable   = true,
                IsIncludedWithUnregisteredDevices = false,
                Name         = FormattableString.Invariant($"tags.{pair.Key}"),
                PropertyType = GetObjectType(pair.Value.Value),
                Value        = pair.Value.Value.ToString()
            });

            var desiredProperties = device.Twin.Properties.Desired.AsEnumerableFlatten().OrderBy(pair => pair.Key).Select(pair => new DevicePropertyValueModel
            {
                DisplayOrder = 2,
                IsEditable   = true,
                IsIncludedWithUnregisteredDevices = false,
                Name           = FormattableString.Invariant($"properties.desired.{pair.Key}"),
                PropertyType   = GetObjectType(pair.Value.Value),
                Value          = pair.Value.Value.ToString(),
                LastUpdatedUtc = pair.Value.LastUpdated
            });

            var reportedProperties = device.Twin.Properties.Reported.AsEnumerableFlatten().Where(pair => !SupportedMethodsHelper.IsSupportedMethodProperty(pair.Key)).OrderBy(pair => pair.Key).Select(pair => new DevicePropertyValueModel
            {
                DisplayOrder = 3,
                IsEditable   = false,
                IsIncludedWithUnregisteredDevices = false,
                Name           = FormattableString.Invariant($"properties.reported.{pair.Key}"),
                PropertyType   = GetObjectType(pair.Value.Value),
                Value          = pair.Value.Value.ToString(),
                LastUpdatedUtc = pair.Value.LastUpdated
            });

            propValModels = tags.Concat(desiredProperties).Concat(reportedProperties);

            hostNameValue = _configProvider.GetConfigurationSettingValue("iotHub.HostName");

            if (!string.IsNullOrEmpty(hostNameValue))
            {
                propValModels = propValModels.Concat(
                    new DevicePropertyValueModel[]
                {
                    new DevicePropertyValueModel()
                    {
                        DisplayOrder = 0,
                        IsEditable   = false,
                        IsIncludedWithUnregisteredDevices = true,
                        Name         = "DeviceID",
                        PropertyType = PropertyType.String,
                        Value        = device.DeviceProperties.DeviceID,
                    },
                    new DevicePropertyValueModel()
                    {
                        DisplayOrder = 0,
                        IsEditable   = false,
                        IsIncludedWithUnregisteredDevices = true,
                        Name         = "HostName",
                        PropertyType = PropertyType.String,
                        Value        = hostNameValue
                    }
                });
            }

            return(propValModels);
        }