Справочная информация:
Я работаю с очень большим решением, которое имеет много сложных компонентов пользовательского интерфейса. В целях отслеживания ошибок мы хотели бы иметь возможность регистрировать любые действия, предпринимаемые пользователем, чтобы мы могли воссоздать (каким-либо образом в сценарии) любую ситуацию, с которой пользователь может столкнуться при использовании графического интерфейса пользователя. Чтобы достичь этой цели, мы хотели бы создать стандарт, который заставляет любой системный компонент, который используется любым компонентом пользовательского интерфейса, реализовывать очень простой интерфейс. Интерфейс будет иметь методы Get, Set и Run. (Журналы / сценарии будут создаваться этими методами.) Все остальные члены производного класса будут частными, за исключением этих методов Get, Set и Run.
Проблема:
Я пытаюсь придумать хороший способ реализации такого интерфейса и должен признать, что я борюсь с некоторыми абстрактными концепциями, необходимыми для этого. Я знаю, как я мог бы сделать это, используя объекты, но я знаю, что приведение объектов может быть дорогим, и решение не будет безопасным для типов. Я только начал изучать дженерики, и кажется, что это может быть лучшим путем, но я борюсь с реализацией. Ниже приведен пример кода, с которым я играл. Для простоты он на самом деле не реализует интерфейс, но он структурирован так, как это должно быть.
Код компилируется и запускается, но я знаю, что не очень хорошо это реализую. Вероятно, я не экономлю на расходах в функциях Get или Set, используя Convert.ChangeType поверх простого приведения объекта. Я также уничтожаю безопасность типов, которую должны предлагать дженерики.
Хотя предложения по любой части этого приветствуются, лучший ответ, вероятно, будет присужден решению, которое показывает, как я должен использовать дженерики для правильной реализации этого. Вот код, с которым я играю, чтобы проиллюстрировать концепцию:
public class TestClass {
public enum SetEnum { Val1, Val2 }
public enum GetEnum { Calculated, Result }
public enum RunEnum { Add, Subtract, Reset }
private double Val1;
private int Val2;
private bool Calculated;
private double Result;
public void Set<T>(SetEnum member, T val) {
switch (member) {
case SetEnum.Val1:
Val1 = (double)Convert.ChangeType(val, Type.GetTypeCode(typeof(double)));
break;
case SetEnum.Val2:
Val2 = (int)Convert.ChangeType(val, Type.GetTypeCode(typeof(int)));
break;
default:
throw new ArgumentOutOfRangeException("variable");
}
}
public T Get<T>(GetEnum member) {
switch (member) {
case GetEnum.Calculated: return (T)Convert.ChangeType(Calculated, Type.GetTypeCode(typeof(T)));
case GetEnum.Result: return (T)Convert.ChangeType(Result, Type.GetTypeCode(typeof(T)));
default: throw new ArgumentOutOfRangeException("member");
}
}
public void Run(RunEnum member) {
switch (member) {
case RunEnum.Add: Add(); break;
case RunEnum.Subtract: Subtract(); break;
case RunEnum.Reset: Reset(); break;
default: throw new ArgumentOutOfRangeException("member");
}
}
private void Add() {
Result = Val1 + Val2;
Calculated = true;
}
private void Subtract() {
Result = Val1 - Val2;
Calculated = true;
}
private void Reset() {
Result = 0;
Calculated = false;
}
}