Dan*_*ars 7 c# architecture enums design-patterns
我正在尝试使用API在给定时间发布值(值和时间元组).这些样本将由数据查看器(例如图表)使用.
我想将值与数量和单位相关联,例如以米为单位的长度.这样我的"观众"可以适当地缩放它.
我正在寻找一种分层枚举,如下所示:
enum Quantity
{
Mass.Kg,
Mass.g,
Length.m,
Length.mm
}
Run Code Online (Sandbox Code Playgroud)
但这在C#中不存在.
我不确定表达这个的最佳模式,我想出了以下内容.是否有一种公认的或更好的方法来做到这一点?
using System;
using Moq;
namespace ConsoleApplication26
{
class Program
{
static void Main(string[] args)
{
//use a Mock to play with the API
Mock<ITelemetryPublisherFactory> mockTelemetryPublisherFactory = new Mock<ITelemetryPublisherFactory>();
var telemetryPublisherFactory = mockTelemetryPublisherFactory.Object;
//example usages
var massTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Double>("My Mass", Mass.Kg);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(83.4);
var lengthTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Int32>("My Height", Length.?m);
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
//10 years time..
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(120.1);
}
}
public interface ITelemetryPublisherFactory
{
ITelemetryPublisher<T> GetChannelSamplePublisher<T>(String channelName, Quantity quantity);
}
public interface ITelemetryPublisher<T>
{
void PublishChannelSampleAtTimeNow(T sampleValue);
}
public abstract class Quantity {}
public class Mass : Quantity
{
private enum Unit
{
g,
Kg
}
private readonly Unit _unit;
private Mass(Unit unit)
{
_unit = unit;
}
public static Quantity Kg {get { return new Mass(Unit.Kg); }}
public static Quantity g { get { return new Mass(Unit.g); } }
public override string ToString()
{
return String.Format("Mass.{0}", _unit);
}
}
public class Length : Quantity
{
private enum Unit
{
m,
mm,
?m,
beardSecond
}
private readonly Unit _unit;
private Length(Unit unit)
{
_unit = unit;
}
public static Quantity m { get { return new Length(Unit.m); } }
public static Quantity mm { get { return new Length(Unit.mm); } }
public static Quantity ?m { get { return new Length(Unit.?m); } }
public static Quantity beardSecond { get { return new Length(Unit.beardSecond); } }
public override string ToString()
{
return String.Format("Length.{0}", _unit);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为最好Unit
为计量单位创建一个类,Quantity
并将计量单位与金额关联起来。查看该想法的数量模式。由于您还想记录测量单位的“类型”,因此您可以创建一个UnitType
记录该信息的类:
public sealed partial class UnitType {
public string Name { get; private set; }
public UnitType(string name) {
Name = name;
}
}
public sealed partial class Unit {
public string Name { get; private set; }
public UnitType Type { get; private set; }
public Unit(string name, UnitType type) {
Name = name;
Type = type;
}
}
Run Code Online (Sandbox Code Playgroud)
(您应该通过覆盖Equals
and使它们成为正确的值类型GetHashCode
)
该类Unit
可以扩展以提供例如转换、复合单元、格式化和解析。
然后,您可以在类中定义常见情况:
public partial class UnitType {
public static readonly UnitType Mass = new UnitType("Mass");
public static readonly UnitType Length = new UnitType("Length");
}
public partial class Unit {
public static readonly Unit Grams = new Unit("g", UnitType.Mass);
public static readonly Unit Kilos = new Unit("kg", UnitType.Mass);
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者用静态类定义你的“层次结构”:
public static class Mass {
public static readonly UnitType Type = new UnitType("Mass");
public static readonly Unit Grams = new Unit("g", Type);
public static readonly Unit Kilos = new Unit("kg", Type);
...
}
public static class Length ...
Run Code Online (Sandbox Code Playgroud)
该类Quantity
也将是一个不可变的值类型(仅显示其用法):
var eniacWeight = new Quantity(27, Mass.Tons);
Run Code Online (Sandbox Code Playgroud)
或者您可以使用扩展方法来创建Quantity
s:
var eniacWeight = 27.Tons();
Run Code Online (Sandbox Code Playgroud)
(来自埃尼阿克)