Добрый день!
Есть класс:
public class MyClass<TData>
{
// хеш от результата применения эцп
public ISignature Signature {get;set}
// ПАРАМЕТРЫ
public long Param1 {get; set}
public string Param2 {get; set}
// и куча других полей
// ТУТ ДАННЫЕ
public TData InnerData {get;set}
}
Нужно реализовать поддержку подписи объектов этого класса.
Однако необходимо дать возможность пользователю создание своего класса.
При этом Signature может быть создана различным алгоритмом ЭЦП, который будет использован (есть ISignatureService).
TData - внутренние данные, они также могут быть заменены пользователем, поэтому стоит generic.
И наибольшая сложность - это блок параметров, есть определенные заданные параметры - long Param1, string Param2.
Общее количество этих параметров может быть изменено пользователем (например, добавлен int Param3 и т.д.)
Signature вычисляется от этих параметров(всех, и дополнительных тоже)
Потом нужно будет добавить сервисы-валидаторы для таких объектов, а также сервисы-фабрики.
Как правильно оформить иерархию классов, интерфейсов, добавить туда generics чтобы оно все было красиво??
Я уже накинул пару вариантов, как это сделать, но я не совсем еще уверен, какой код окажется в итоге лучше и проще.
Вариант 1public interface IClassHeader{
long Param1 {get;}
string Param2 {get;}
}
public interface IMyObj<THeader, TData> where THeader: IClassHeader{
ISignature Signature { get; }
THeader Header {get;}
TData InnerData {get;}
}
public class MyHeader: IClassHeader { ...}
public class MyObj: IMyObj<MyHeader, string> { ... }
public interface IMyObjValidator<TObj, THeader, TData>
where TObj: IMyObj<THeader, TData>
where THeader: IClassHeader {
bool CheckSignature(TObj inputObject);
}
Вариант 2public interface IObjectWithParams{ //пользователь расширяет именно его
ISignature Signature {get;}
long Param1 {get;}
string Param2 {get;}
}
public interface ICheckableObject {
bool CheckSignature(IMyObjValidationAlgorithm algorithm);
}
public interface ISignableObject {
void SignObject(ISignatureService service);
}
public interface IDataObject<TData> : IObjectWithParams {
TData Data {get;}
}
public interface IMyObject<TData>: IDataObject<TData>, ICheckableObject, ISignableObject {}
public class MyObject: IMyObject<string> {
...
private ISignature _signature = null;
void ISignableObject.Sign(ISignatureService service) {
var sign = service.Sign(this);
_signature = sign;
}
public ISignature Signature => _signature
}
Соответственно в первом варианте будет специальный класс, который принимает IClassHeader и вычисляет хеш от подписанного блока с параметрами, а во втором - по аналогии с ICheckableObject, будет реализовано заполнение поля Signature специальным классом. Есть еще мысля что второй вариант напоминает мне пример паттерна Visitor.
Как будет лучше?