private void AddContractInfo(Type componentContractType, ComponentContractInfo componentContractInfo) { List <ComponentContractInfo> contractList; if (_componentContracts.ContainsKey(componentContractType)) { contractList = _componentContracts[componentContractType]; } else { contractList = new List <ComponentContractInfo>(); _componentContracts[componentContractType] = contractList; } contractList.Add(componentContractInfo); }
/// <summary> /// Special method to register contract directly. /// Should be used only by KioskApplicationBase. /// </summary> internal void RegisterContractInternal <TComponentContract>(string componentRole, ComponentContractInfo componentContractInfo) { Assure.ArgumentNotNull(componentRole, nameof(componentRole)); Assure.ArgumentNotNull(componentContractInfo, nameof(componentContractInfo)); var contactType = typeof(TComponentContract); Assure.CheckFlowState(contactType.IsInterface, $"{contactType.FullName} is not interface."); _componentsByRole[componentRole] = componentContractInfo.Component; AddContractInfo(contactType, componentContractInfo); }
private void RegisterComponentContracts(ComponentBase component, Type[] componentContracts) { if (componentContracts == null || componentContracts.Length == 0) { // component doesn't implement any contracts return; } var componentType = component.GetType(); foreach (var componentContractType in componentContracts // ignore contract duplicates .Distinct()) { if (!componentContractType.IsInterface || !typeof(IComponentContract).IsAssignableFrom(componentContractType)) { Log.Error(LogContextEnum.Configuration, $"Component contract '{componentContractType.FullName}' is not an interface or doesn't inherit {nameof(IComponentContract)}."); continue; } if (!componentContractType.IsAssignableFrom(componentType)) { Log.Error(LogContextEnum.Configuration, $"Component '{componentType.FullName}' returned contract '{componentContractType.FullName}' that is not implemented by the component."); continue; } var contractStatusProperty = componentContractType.GetProperty(ContractStatusPropertyName); if (contractStatusProperty == null || !contractStatusProperty.CanRead || contractStatusProperty.CanWrite || contractStatusProperty.PropertyType != typeof(BindableComponentStatus)) { Log.Error(LogContextEnum.Configuration, $"Component contract '{componentContractType.FullName}' doesn't declare readable-only {ContractStatusPropertyName} property of type {nameof(BindableComponentStatus)} (required by convention)."); continue; } var contractStatus = (BindableComponentStatus)contractStatusProperty.GetValue(component); // check if separate contract status if (contractStatus != component.Status) { if (contractStatus == null) { Log.Error(LogContextEnum.Configuration, $"Component contract '{componentContractType.FullName}' status is null."); continue; } // todo: add support for a separate contract statuses (see architecture docs) // bind separate contract status to component status (status inheritance) // implement appropriate monitoring representation } ComponentState contractState = null; var contractStateProperty = componentContractType.GetProperty(ContractStatePropertyName); if (contractStateProperty != null && contractStateProperty.CanRead) { // no need to check on null - it's already checked contractState = (ComponentState)contractStateProperty.GetValue(component); } var componentContractInfo = new ComponentContractInfo(component, contractStatus, contractState); AddContractInfo(componentContractType, componentContractInfo); } }