Rikrop.Core.Framework.dll
Эта библиотека содержит множество наиболее обобщенных инструментов, которые находят применение из проекта в проект. Рассмотрим чуть подробнее каждое пространство имен.namespace Rikrop.Core.Framework
Сюда мы поместили те классы и инструменты, которые являются инфраструктурными.public static class CollectionExtentions
Поскольку коллекции в .NET развивались вместе с самим фреймворком, не каждый из контейнеров получил удобный интерфейс манипуляции данными. Здесь мы собрали методы расширения, которые решают эту проблему. Мы вставляем, добавляем, перебираем, ищем и осуществляем слияние.public static class CryptoHelper
К счастью, в .NET есть классы для работы алгоритмами шифрования, цифровой подписи и хеширования. К сожалению, их интерфейс довольно громоздкий. Для себя мы сделали маленький класс с единственным методом:public static string GetShaHash(string str) { ... }
public class DateRange
Класс представляет собой тип данных для хранения диапозонов дат, при этом диапозон может быть открытым. Экземпляры умеют сравнивать себя с другими, округлять до целых дней и сериализоваться.public interface ITodayNowProvider + public class TodayNowProvider + public interface IDateTimeProvider + public class DateTimeProvider : IDateTimeProvider
Мы често работаем с временем и столкнулись с проблемой покрытия кода, связанного с определением времени относительно текущего. А еще очень часто оказалось важным иметь доступ к таким данным как "текущий месяц", "прошлая неделя". Реализация DateTimeProvider и чудесный класс DateRange дали возможность с лёгкостью манипулировать типов данных DateTime. Вот простой пример mock для тестирования функционала, использующего провайдер даты-времени.var today = new DateTime(2013, 05, 2); var dateTimeProvider = Mock.Create<IDateTimeProvider>(); Mock.Arrange(() => dateTimeProvider.Today).Returns(today);
А вот вкратце и без излишних комментариев и интерфейс IDateTimeProvider
public interface IDateTimeProvider
{
DateTime Now { get; }
DateTime UtcNow { get; }
DateTime Today { get; }
DateRange GetLogicalDateRange(DateTime dateFrom, DateTime dateTo, int dayStartHour);
DateRange GetFactDateRange(DateTime logicDateFrom, DateTime logicDateTo, int dayStartHour);
DateRange MaxRange();
DateRange GetMonthAgo(int monthCount = -1);
DateRange GetCurrentMonth();
DateRange GetToday();
DateRange GetYesterday();
DateRange GetCurrentWeek();
DateRange GetLastWeek();
DateRange GetTwoWeeksAgo();
DateRange GetLastMonth();
}
public static class ExpressionHelper
Мы активно работаем над строгой типизацией и статической проверкой в коде, поэтому активно используем работу с деревьями выражений (Expressions). В этом классе собраны важные, хоть и редкоприменимые методы для разбора и получения информации из деревьев выражений.public static class SerializerExtention
В .NET нет такого удобного инструмента как generic-serializer. У нас он есть.public interface ITimer + public class SimpleTimer : ITimer + public class RepeatableExecutor
Мы решили абстрагироваться от множества реализаций таймеров, которые есть в .NET и переносимо между платформами решить наиболее частую задачу, в которой применяются таймера - повторяемый запуск определенного события.namespace Rikrop.Core.Framework.ActiveDirectory
Интеграция приложений с AD является важной темой. В .NET на данный момент существует несколько подходов к работе с сущностями домена, однако для типовых задач часто хватает ограниченного набора функций. Основным классом здесь является ADManager.public interface IADManager
{
IEnumerable<ADUserEntity> GetUsersInGroup(string groupName, bool recursive);
IEnumerable<ADUserEntity> GetAllUsers();
IEnumerable<ADUserEntity> GetUsersWithNameAndLastName();
IEnumerable<ADGroupEntity> GetUserGroups(string userIdentity);
IEnumerable<ADGroupEntity> GetAllGroups();
bool ValidateAuthorization();
}
Стоит отметить, что это лишь базовый набор функций, каждое приложение ставит свои требования и единого интерфейса для интеграции с различной структурой AD заказчиков достичь очень проблематично, но мы всегда строим свои системы максимально настраиваемыми и универсальными.
namespace Rikrop.Core.Framework.Exceptions
Для обработки исключений мы используем механизм, схожий с Exception Handling Application Block из Enterprise library. Вместе с этим, мы постарались упростить механизм обработки исключений.public interface IExceptionHandler
{
bool Handle(Exception exception);
}
У нас нет готовых обработчиков, пока двух одинаковых решений по обработке исключений в наших проектах не встретилось. Но фреймворк поддерживается в максимально актуальном состоянии и как только типовое решение появится - мы сразу добавим его. В Enterprise library логирование может быть организовано через подсистему обработки ошибок, но у нас мухи отделены от перехвата исключений.
namespace Rikrop.Core.Framework.Logging
Поскольку логирование событий необходимо практически в каждом приложении, мы вынесли инфраструктуру для логирования в общую сборку.public interface ILoggerFactory
{
ILogger CreateForSource(string logSource);
}
public interface ILogger
{
void Log<TRecord>(TRecord record) where TRecord : ILogRecord;
}
public interface ILogRecord
{
LogRecordLevel LogLevel { get; }
string Message { get; }
LogRecordDataValue[] DataValues { get; }
bool HasDataValues { get; }
}
Мы не стали реализовывать в базовой библиотеке конкретные логгеры, вместо этого можно подключить библиотеки Rikrop.Core.Logging.dll и Rikrop.Core.Logging.NLog.dll. По необходимости всегда можно написать свой логгер, но пока необходимости в этом не возникало.namespace Rikrop.Core.Framework.Services
Взаимодействие с уровнем сервисов занимает очень важное место в нашем фреймворке. Если рассматривать клиентскую сторону взаимодействия, то мы приняли концепцию работы с сервисами через Executor'ы, которые могут обладать некоторыми дополнительными свойствами в зависимости от контекста. Например, для работы в ViewModel на время запуска метода сервиса может исполняться триггер для извещения интерфейса о том, что приложение занято. Точкой входа является интерфейсpublic interface IServiceExecutor<out TService>
{
Task Execute(Func<TService, Task> action);
Task<TResult> Execute<TResult>(Func<TService, Task<TResult>> func);
}
Комментариев нет:
Отправить комментарий