Skip to content

Commit

Permalink
T #98 working on reflection mapper
Browse files Browse the repository at this point in the history
  • Loading branch information
HueByte committed Oct 25, 2022
1 parent 81cf37b commit bd67fcd
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuppyService.Core.Abstraction
{
public interface IReflectionMappableToT<T> where T : class { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuppyService.Core.Abstraction
{
[AttributeUsage(AttributeTargets.Property)]
public class MappableToAttribute : Attribute
{
public Type MappableTo;
public string AlternativeName;
public MappableToAttribute(Type type, string mappingName)
{
MappableTo = type;
AlternativeName = mappingName;
}
}
}
2 changes: 2 additions & 0 deletions src/HuppyService/HuppyService.Core/Models/CommandLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class CommandLog : DbModel<int>
public override int Id { get; set; }
public string? CommandName { get; set; }
public string? ErrorMessage { get; set; }

[MappableTo(typeof(ulong), "UnixTime")]
public DateTime? Date { get; set; }
public bool IsSuccess { get; set; }
public long ExecutionTimeMs { get; set; }
Expand Down
77 changes: 77 additions & 0 deletions src/HuppyService/HuppyService.Core/Utilities/ReflectionMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using HuppyService.Core.Abstraction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace HuppyService.Core.Utilities
{
public static class ReflectionMapper
{
public static D? Map<T, D>(T input)
where T : class
where D : class, new()
{
//var type1 = typeof(T);
//var type2 = typeof(D);

// create instance of D
D result = new();

// get props of D
var propsOfD = typeof(D).GetProperties();

// get props of T
var propsOfT = input.GetType().GetProperties();

// map props to each other via names
foreach (var tProp in propsOfT)
{
MappableToAttribute? attributeInfo = tProp.GetCustomAttribute(typeof(MappableToAttribute)) as MappableToAttribute;
//string searchName = attributeInfo is not null ? attributeInfo.AlternativeName : tProp.Name;

// get instance of D prop
PropertyInfo propInfo;
if (attributeInfo != null)
propInfo = propsOfD.First(prop => prop.Name == tProp.Name || prop.Name == attributeInfo.AlternativeName);
else
propInfo = propsOfD.First(prop => prop.Name == tProp.Name);

//PropertyInfo propInfo = propsOfD.First(prop => prop.Name == searchName);
var propInstance = propInfo.GetValue(result, null);

propInfo.SetValue(result, GetFinalProperty(attributeInfo, propInstance));
}

return result;
}

public static object? GetFinalProperty(MappableToAttribute? attributeInfo, object? instance)
{
// get Mappable attribute
//MappableToAttribute? attributeInfo = propInfo.GetCustomAttribute(typeof(MappableToAttribute)) as MappableToAttribute;

// get instance of value
//var value = propInfo.GetValue(instance, null);

// perform custom mappings
if (attributeInfo is not null)
{
if (instance is DateTime dateValue && attributeInfo.MappableTo == typeof(ulong))
{
return Miscellaneous.DateTimeToUnixTimeStamp(dateValue);
}
else if (instance is ulong ulongValue && attributeInfo.MappableTo == typeof(DateTime))
{
return Miscellaneous.UnixTimeStampToUtcDateTime(ulongValue);
}

return instance;
}

return instance;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuppyService.Core.Utilities
{
internal class ReflectionMapperHelpers
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ message ReminderModel {
}

message TicketModel {
int32 Id = 1;
string Id = 1;
string Topic = 2;
string Description = 3;
bool IsClosed = 4;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using HuppyService.Core.Interfaces.IRepositories;
using HuppyService.Core.Models;
using HuppyService.Core.Utilities;
using HuppyService.Service.Protos;
using HuppyService.Service.Protos.Models;
Expand Down Expand Up @@ -56,6 +57,8 @@ public override async Task<AverageTimeResponse> GetAverageExecutionTime(Protos.V

public override async Task<CommandLogModel> AddCommand(CommandLogModel request, ServerCallContext context)
{
var test = ReflectionMapper.Map<CommandLogModel, CommandLog>(request);
//ReflectionMapper
Core.Models.CommandLog commandLog = new()
{
ChannelId = request.ChannelId,
Expand Down
106 changes: 95 additions & 11 deletions src/HuppyService/HuppyService.Service/Services/TicketService.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
using Grpc.Core;
using Google.Protobuf;
using Grpc.Core;
using HuppyService.Core.Interfaces.IRepositories;
using HuppyService.Core.Models;
using HuppyService.Core.Utilities;
using HuppyService.Service.Protos;
using HuppyService.Service.Protos.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.Net.Sockets;

namespace HuppyService.Service.Services
{
Expand All @@ -14,29 +19,108 @@ public TicketService(ITicketRepository ticketRepository)
_ticketRepository = ticketRepository;
}

public override Task<TicketModel> AddTicket(AddTicketInput request, ServerCallContext context)
public override async Task<TicketModel> AddTicket(AddTicketInput request, ServerCallContext context)
{
return base.AddTicket(request, context);
if (string.IsNullOrEmpty(request.Description)) throw new ArgumentException("Ticket description cannot be null");

Ticket ticket = new()
{
Id = Guid.NewGuid().ToString(),
Topic = request.Topic,
Description = request.Description,
CreatedDate = DateTime.UtcNow,
TicketAnswer = null,
ClosedDate = null,
IsClosed = false,
UserId = request.UserId,
};

await _ticketRepository.AddAsync(ticket);
await _ticketRepository.SaveChangesAsync();

return new TicketModel()
{
Id = ticket.Id,
UserId = ticket.UserId,
Description = ticket.Description,
Topic = ticket.Topic,
IsClosed = ticket.IsClosed,
TicketAnswer = ticket.TicketAnswer,
ClosedDate = ticket.ClosedDate is null ? 0 : Miscellaneous.DateTimeToUnixTimeStamp((DateTime)ticket.ClosedDate),
CreatedDate = Miscellaneous.DateTimeToUnixTimeStamp(ticket.CreatedDate)
};
}

public override Task<CommonResponse> CloseTicket(CloseTicketInput request, ServerCallContext context)
public override async Task<CommonResponse> CloseTicket(CloseTicketInput request, ServerCallContext context)
{
return base.CloseTicket(request, context);
if (string.IsNullOrEmpty(request.TicketId))
throw new ArgumentException("Ticked ID cannot be empty");

var ticket = await _ticketRepository.GetAsync(request.TicketId);

if (ticket is null) throw new Exception("Ticket doesn't exist");

ticket.IsClosed = true;
ticket.TicketAnswer = request.Answer;
ticket.ClosedDate = DateTime.UtcNow;

await _ticketRepository.UpdateAsync(ticket);
await _ticketRepository.SaveChangesAsync();

return new CommonResponse() { IsSuccess = true };
}

public override Task<Protos.Int32> GetCountAsync(UserId request, ServerCallContext context)
public override async Task<Protos.Int32> GetCountAsync(UserId request, ServerCallContext context)
{
return base.GetCountAsync(request, context);
var tickets = await _ticketRepository.GetAllAsync();

// modify database query
var result = await tickets.Where(ticket => ticket.UserId == request.Id).CountAsync();
return new Protos.Int32() { Number = result };
}

public override Task<TicketModelCollection> GetPaginatedTickets(GetPaginatedTicketsInput request, ServerCallContext context)
public override async Task<TicketModelCollection> GetPaginatedTickets(GetPaginatedTicketsInput request, ServerCallContext context)
{
return base.GetPaginatedTickets(request, context);
var tickets = (await _ticketRepository.GetAllAsync())
.OrderBy(ticket => ticket.IsClosed)
.ThenByDescending(ticket => ticket.CreatedDate)
.Skip(request.Skip)
.Take(request.Take)
.ToList();

var result = new TicketModelCollection();
result.TicketsModels.AddRange(tickets.Select(ticket => new TicketModel
{
Id = ticket.Id,
UserId = ticket.UserId,
Description = ticket.Description,
Topic = ticket.Topic,
IsClosed = ticket.IsClosed,
TicketAnswer = ticket.TicketAnswer,
ClosedDate = ticket.ClosedDate is null ? 0 : Miscellaneous.DateTimeToUnixTimeStamp((DateTime)ticket.ClosedDate),
CreatedDate = Miscellaneous.DateTimeToUnixTimeStamp(ticket.CreatedDate)
}));

return result;
}

public override Task<TicketModel> GetTicket(GetTicketInput request, ServerCallContext context)
public override async Task<TicketModel> GetTicket(GetTicketInput request, ServerCallContext context)
{
return base.GetTicket(request, context);
var ticket = await _ticketRepository.GetAsync(request.TicketId);

if (ticket is null) return null!;

return new TicketModel
{
Id = ticket.Id,
UserId = ticket.UserId,
Description = ticket.Description,
Topic = ticket.Topic,
IsClosed = ticket.IsClosed,
TicketAnswer = ticket.TicketAnswer,
ClosedDate = ticket.ClosedDate is null ? 0 : Miscellaneous.DateTimeToUnixTimeStamp((DateTime)ticket.ClosedDate),
CreatedDate = Miscellaneous.DateTimeToUnixTimeStamp(ticket.CreatedDate)
};
}

public override Task<TicketModelCollection> GetTickets(Protos.Void request, ServerCallContext context)
Expand Down

0 comments on commit bd67fcd

Please sign in to comment.