/// <summary> /// Creates a data transfer object from a given view model. /// The view model must use <see cref="DtoAttribute"/> and <see cref="DtoPropertyAttribute"/> for the conversion to work. /// </summary> /// <typeparam name="TDto">The data transfer object type to create.</typeparam> /// <param name="viewModel">The view model to convert.</param> /// <returns>The converted data transfer object.</returns> public static TDto ToDto <TDto>(this ViewModel viewModel) where TDto : class { if (viewModel == null) { throw new ArgumentNullException(nameof(viewModel)); } var dtoAttr = DtoAttribute.GetDtoAttribute(viewModel.GetType()); if (dtoAttr == null) { throw new InvalidOperationException("The given view data transfer object has no DtoAttribute defined."); } if (!dtoAttr.Type.IsAssignableFrom(typeof(TDto))) { throw new InvalidCastException($"Cannot cast the data transfer object attribute type {dtoAttr.Type.Name} into the desired type {typeof(TDto).Name}."); } TDto result = (TDto)Activator.CreateInstance(dtoAttr.Type) !; foreach (var propertyInfo in viewModel.GetType().GetProperties()) { var dtoPropertyAttr = DtoPropertyAttribute.GetDtoPropertyAttribute(propertyInfo); if (dtoPropertyAttr == null) { continue; } var dtoPropertyInfo = dtoAttr.Type.GetProperty(dtoPropertyAttr.PropertyName); if (dtoPropertyInfo == null) { throw new InvalidOperationException($"There is no property called {dtoPropertyAttr.PropertyName} for the data transfer object type {dtoAttr.Type.Name}."); } dtoPropertyInfo.SetValue(result, propertyInfo.GetValue(viewModel, null), null); } return(result); }
/// <summary> /// Creates a view model from a given data transfer object. /// The view model must use <see cref="DtoAttribute"/> and <see cref="DtoPropertyAttribute"/> for the conversion to work. /// </summary> /// <typeparam name="TViewModel">The view model type to create.</typeparam> /// <param name="dto">The data transfer object to convert.</param> /// <returns>The converted view model.</returns> public static TViewModel ToViewModel <TViewModel>(this object dto) where TViewModel : ViewModel { if (dto == null) { throw new ArgumentNullException(nameof(dto)); } var dtoAttr = DtoAttribute.GetDtoAttribute(typeof(TViewModel)); if (dtoAttr == null) { throw new InvalidOperationException("The given view model has no DtoAttribute defined."); } if (!dtoAttr.Type.IsAssignableFrom(dto.GetType())) { throw new InvalidCastException($"Cannot cast the data transfer object attribute type {dtoAttr.Type.Name} into the given type {dto.GetType().Name}."); } TViewModel result = (TViewModel)Activator.CreateInstance(typeof(TViewModel)) !; foreach (var propertyInfo in typeof(TViewModel).GetProperties()) { var dtoPropertyAttr = DtoPropertyAttribute.GetDtoPropertyAttribute(propertyInfo); if (dtoPropertyAttr == null) { continue; } var dtoPropertyInfo = dtoAttr.Type.GetProperty(dtoPropertyAttr.PropertyName); if (dtoPropertyInfo == null) { throw new InvalidOperationException($"There is no property called {dtoPropertyAttr.PropertyName} for the data transfer object type {dtoAttr.Type.Name}."); } propertyInfo.SetValue(result, dtoPropertyInfo.GetValue(dto, null), null); } return(result); }
private static TViewModel ToViewModel <TViewModel>(object dto, List <object> visitedDtos) where TViewModel : ViewModel { if (dto == null) { throw new ArgumentNullException(nameof(dto)); } if (visitedDtos.Contains(dto)) { throw new NotSupportedException("Cyclic relationships are not supported!"); } visitedDtos.Add(dto); var dtoAttrs = DtoAttribute.GetDtoAttributes(typeof(TViewModel)); if (!dtoAttrs.Any()) { throw new InvalidOperationException("The given view model has no DtoAttribute defined."); } var dtoAttr = dtoAttrs.FirstOrDefault(attr => attr.Type.IsAssignableFrom(dto.GetType())); if (dtoAttr == null) { throw new InvalidCastException($"There is no DtoAttribute assignable to the given type {dto.GetType().Name}."); } TViewModel result = (TViewModel)Activator.CreateInstance(typeof(TViewModel)) !; foreach (var propertyInfo in typeof(TViewModel).GetProperties()) { var dtoPropertyAttrs = DtoPropertyAttribute.GetDtoPropertyAttributes(propertyInfo); if (!dtoPropertyAttrs.Any()) { continue; } var dtoPropertyAttr = dtoPropertyAttrs.FirstOrDefault(attr => attr.Type == null || attr.Type.IsAssignableFrom(dto.GetType())); if (dtoPropertyAttr == null) { continue; } var dtoPropertyInfo = dtoAttr.Type.GetProperty(dtoPropertyAttr.PropertyName); if (dtoPropertyInfo == null) { throw new InvalidOperationException($"There is no property called {dtoPropertyAttr.PropertyName} for the data transfer object type {dtoAttr.Type.Name}."); } object?valueToConvert = dtoPropertyInfo.GetValue(dto, null); object?valueToSet; if (typeof(ViewModel).IsAssignableFrom(propertyInfo.PropertyType)) { if (valueToConvert == null) { continue; } MethodInfo genericToViewModel = _internalToViewModelInfo.MakeGenericMethod(propertyInfo.PropertyType); valueToSet = genericToViewModel.Invoke(null, new[] { valueToConvert, visitedDtos }); } else if (HelperExtensions.IsTypeIList(dtoPropertyInfo.PropertyType) && HelperExtensions.IsTypeObservableViewModelCollection(propertyInfo.PropertyType)) { if (valueToConvert == null) { continue; } var collection = Activator.CreateInstance(propertyInfo.PropertyType, new[] { result }) !; MethodInfo genericToViewModel = _internalToViewModelInfo.MakeGenericMethod(propertyInfo.PropertyType.GenericTypeArguments.First()); foreach (var item in (IEnumerable)valueToConvert) { ((IList)collection).Add(genericToViewModel.Invoke(null, new[] { item, visitedDtos })); } valueToSet = collection; } else { valueToSet = valueToConvert; } propertyInfo.SetValue(result, valueToSet, null); } return(result); }