У меня есть два класса-близнеца, представляющие «одни и те же» объекты: один определен для вычислительных вычислений, а другой — для привязки пользовательского интерфейса. Я хотел бы уменьшить дублированный код и ошибки. Я определил общий интерфейс и переместил все общие статические методы, используя методы расширения.
Не хватает того, как определить проверку свойств в одном месте .
Сейчас я использую System.ComponentModel.DataAnnotations, но мне нужно определить одни и те же аннотации для обоих классов. В базовом классе я использую DataAnnotation для проверки десериализации JSON, в то время как в пользовательском интерфейсе используются те же значения.
Я не могу использовать наследование, поскольку класс пользовательского интерфейса уже наследуется от класса ViewModel, а множественное наследование не поддерживается. разрешено.
Есть ли другой подход или идея?
Здесь проект с той же основной концепцией.
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
namespace myRefactoring
{
public interface IShape
{
// would be nice to define the DataAnnotation here
// but it's not working with interfaces
public int N { get; set; }
public double side { get; set; }
public double perimeter { get; }
public double area { get; }
}
public class Shape : IShape
{
///
/// main class for math evaluations
///
[Range(3, int.MaxValue, ErrorMessage = "at least 3 sides")]
public int N { get; set; }
[Range(double.Epsilon, double.MaxValue, ErrorMessage = "just positive size")]
public double side { get; set; }
public Shape(int N, double S) { this.N = N; this.side = S; }
public double perimeter => ShapeExtension.perimeter(this);
public double area => ShapeExtension.area(this);
}
public class ShapeUI : ViewModel, IShape, INotifyPropertyChanged
{
///
/// class for UI binding
/// NotifyPropertyChanged ...
///
public event PropertyChangedEventHandler? PropertyChanged;
public ShapeUI(int N, double S) { this._N = N; this._side = S; }
private int _N;
[Range(3, int.MaxValue, ErrorMessage = "at least 3 sides")]
public int N {
get => _N;
set {
_N = value;
NotifyPropertyChanged();
NotifyPropertyChanged(nameof(perimeter));
NotifyPropertyChanged(nameof(area));
}
}
private double _side;
[Range(double.Epsilon, double.MaxValue, ErrorMessage = "just positive size")]
public double side {
get => _side;
set {
if (value != this._side)
{
this._side = value;
NotifyPropertyChanged();
NotifyPropertyChanged(nameof(perimeter));
NotifyPropertyChanged(nameof(area));
}
}
}
public double perimeter => ShapeExtension.perimeter(this);
public double area => ShapeExtension.area(this);
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Console.WriteLine("changing " + propertyName);
}
}
public static class ShapeExtension
{
public static double perimeter(this IShape s) => s.N * s.side;
public static double area(this IShape s) => Math.Pow(s.side / 2, 2) / Math.Tan(Math.PI / s.N) * s.N;
}
public class ViewModel
{
// class implementing ViewModel methods and variables
}
internal class Program
{
static void Main(string[] ars)
{
Console.WriteLine("Create triangle");
Shape triangle = new(3, 1.0);
Console.WriteLine($"area = {triangle.area:F3}");
Console.WriteLine("\n\nCreate square");
ShapeUI square = new(4, 1.0);
Console.WriteLine($"area = {square.area:F3}");
Console.WriteLine("\n\nModify square");
square.side = 2.0;
Console.WriteLine($"area = {square.area:F3}");
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... -interface