我有不同属性的网络打印机(例如支持的网络协议、语言、状态、打印模式)。
public abstract class PrinterAttribute
{
protected PrinterAttribute(int value, string dsc)
{
this.Value = value;
this.Dsc = dsc;
}
protected PrinterAttribute(int value, string dsc, Enum type) : this(value, dsc)
{
this.Type = type;
}
protected int Value { get; private set; }
protected string Dsc { get; private set; }
protected Enum Type { get; private set; }
}
最后,我将有许多类,如NetworkProtocolAttribute
、PrinterModeAttribute
。
public class NetworkProtocolAttribute : PrinterAttribute
{
public NetworkProtocolAttribute(int value, string dsc) : base(value, dsc) {}
public NetworkProtocolAttribute(int value, string dsc, ProtocolType protocolType) : base(value, dsc, protocolType) {}
#region 1. way - get desired network protocol from locating it in all possible ones
// all possible network protocols that a printer can support
private static IList<NetworkProtocolAttribute> allPossibleProtocols;
private static IList<NetworkProtocolAttribute> AllPossibleProtocols
{
get
{
if(allPossibleProtocols == null)
{
allPossibleProtocols = new List<NetworkProtocolAttribute>()
{
new NetworkProtocolAttribute(0, "None"),
new NetworkProtocolAttribute(1, "FTP"),
new NetworkProtocolAttribute(2, "LPD"),
new NetworkProtocolAttribute(4, "TCP"),
new NetworkProtocolAttribute(8, "UDP"),
new NetworkProtocolAttribute(0x10, "HTTP"),
new NetworkProtocolAttribute(0x20, "SMTP"), // simple mail transfer protocol
new NetworkProtocolAttribute(0x40, "POP3"),
new NetworkProtocolAttribute(0x80, "SNMP"), // simple network management protocol
new NetworkProtocolAttribute(0x100, "Telnet"),
new NetworkProtocolAttribute(0x200, "Weblink"),
new NetworkProtocolAttribute(0x400, "TLS"),
new NetworkProtocolAttribute(0x800, "HTTPS")
};
}
return allPossibleProtocols;
}
}
public static NetworkProtocolAttribute SMTP_FirstWay
{
get
{
// don't like it because you locate it by value
return AllPossibleProtocols.Single(x => x.Value == 0x80);
}
}
#endregion
#region 2. way - create public static NetworkProtocol for every possible protocol
private static NetworkProtocolAttribute smtp;
public static NetworkProtocolAttribute SMTP_SecondWay
{
get
{
if( smtp == null)
{
smtp = new NetworkProtocolAttribute(0x80, "SNMP");
}
return smtp;
}
}
#endregion
#region 3. way - create enum and find it by enum
public enum ProtocolType : int
{
None,
FTP,
LPD,
TCP,
UDP,
HTTP,
SMTP,
POP3,
SNMP,
Telnet,
Weblink,
TLS,
HTTPS
}
private static IList<NetworkProtocolAttribute> allPossibleProtocols3;
protected static IList<NetworkProtocolAttribute> AllPossibleProtocols3
{
get
{
if (allPossibleProtocols3 == null)
{
allPossibleProtocols3 = new List<NetworkProtocolAttribute>()
{
new NetworkProtocolAttribute(0, "None", ProtocolType.None),
new NetworkProtocolAttribute(1, "FTP", ProtocolType.FTP),
new NetworkProtocolAttribute(2, "LPD", ProtocolType.LPD),
new NetworkProtocolAttribute(4, "TCP", ProtocolType.TCP),
new NetworkProtocolAttribute(8, "UDP", ProtocolType.UDP),
new NetworkProtocolAttribute(0x10, "HTTP", ProtocolType.HTTP),
new NetworkProtocolAttribute(0x20, "SMTP", ProtocolType.SMTP),
new NetworkProtocolAttribute(0x40, "POP3", ProtocolType.POP3),
new NetworkProtocolAttribute(0x80, "SNMP", ProtocolType.SNMP),
new NetworkProtocolAttribute(0x100, "Telnet", ProtocolType.Telnet),
new NetworkProtocolAttribute(0x200, "Weblink", ProtocolType.Weblink),
new NetworkProtocolAttribute(0x400, "TLS", ProtocolType.Telnet),
new NetworkProtocolAttribute(0x800, "HTTPS", ProtocolType.HTTPS)
};
}
return allPossibleProtocols3;
}
}
public static NetworkProtocolAttribute GetProtocol_ThirdWay(ProtocolType protocolType)
{
NetworkProtocolAttribute match = AllPossibleProtocols3.Where(x => x.Type.Equals(protocolType)).SingleOrDefault();
return match;
}
#endregion
最后,如何通过网络打印机获得所需的协议支持:
class Program
{
static void Main(string[] args)
{
// 1. way
NetworkProtocolAttribute protocol1 = NetworkProtocolAttribute.SMTP_FirstWay;
// 2. way
NetworkProtocolAttribute protocol2 = NetworkProtocolAttribute.SMTP_SecondWay;
// 3. way
NetworkProtocolAttribute protocol3 = NetworkProtocolAttribute.GetProtocol_ThirdWay(
NetworkProtocolAttribute.ProtocolType.SMTP);
Console.ReadKey();
}
我喜欢的是1和3。方法是,您看到了所有可能的协议的列表。3. way也只有一种获得协议的方法,而2. way对于每种协议都有一种方法。
发布于 2019-05-20 10:05:15
比较
这看起来像是某种自定义枚举类型,但以它当前的形式来说,它并不是很有用:
PrinterAttribute
中的所有属性都是protected
,这意味着只有派生类才能访问它们。这对其他代码不太有用。Enum
类型的属性使用起来很麻烦,因为它的类型太弱。它只告诉您它是一个枚举,而不是哪个枚举,因此您仍然不知道哪些值是有效的。Value
属性。NetworkProtocolAttribute.FTP == new NetworkProtocolAttribute(1, "FTP")
失败了,因为它们不是同一个实例。调用Equals
也是如此。您将希望实现相关的操作符,并覆盖标准的Equals
方法(以及使用它,也包括GetHashCode
)。实现IEquatable<T>
也是一个好主意。你考虑过用普通的枚举代替吗?
[Flags] // Indicates that this enum is intended to be used as a bitmask
public enum Protocol // No need to specify int as underlying type
{
None = 0x00,
FTP = 0x01,
LPD = 0x02,
TCP = 0x04,
UDP = 0x08,
HTTP = 0x10,
SMTP = 0x20,
// and so on
}
// Use:
var protocol = Protocol.FTP;
protocol.ToString(); // -> "FTP"
var protocols = Protocol.FTP | Protocol.UDP;
protocols.HasFlag(Protocol.UDP); // -> true
Enum.GetValues(typeof(Protocol)); // -> Protocol[] { None, FTP, LDP, ... }
如果确实需要,可以向这些值添加[Description("...")]
属性,但是枚举名称本身已经足够描述性了。如果您将这些描述用于显示目的,那么最好在UI层(由于本地化等原因)这样做。
IList<T>
用于静态只读属性:它允许其他代码修改列表。改用IEnumerable<T>
、IReadOnlyCollection<T>
或IReadOnlyList<T>
。另外,使用实际的ReadOnlyCollection<T>
(List<T>
有一个方便的AsReadOnly
方法)。Foo MyProperty { get; } = new Foo();
,因此不需要显式定义字段并在getter中执行空检查。顺便说一句,这种空检查方法并不是线程安全的,所以如果您确实需要延迟初始化,可以使用Lazy<T>
或LazyInitializer
。NetworkProtocolAttribute protocol1 = NetworkProtocolAttribute.SMTP_FirstWay;
可缩短为var protocol1 = NetworkProtocolAttribute.SMTP_FirstWay;
。这样编译器就可以推断类型,所以如果从右边已经很明显的话,就不需要写两次类型了。.Where(...).FirstOrDefault()
可以简化为.FirstOrDefault(...)
。this.
。属性是用PascalCase编写的,参数是用camelCase编写的,所以Value = value;
对我来说很清楚。Description
完全可读性是很重要的,特别是从长远来看,在自动完成工具的帮助下编写并不需要那么多时间。System.Attribute
继承的,这显然不是您想要的,所以您可能需要选择不同的名称以避免混淆。最后,关于#1和#3中的线性查找,您可以通过反转列表和其他属性之间的关系来消除这些查询:
public static NetworkProtocolAttribute FTP { get; } = new NetworkProtocolAttribute(1, "FTP");
public static NetworkProtocolAttribute LPD { get; } = new NetworkProtocolAttribute(2, "LPD");
// and so on...
public static IReadOnlyList<NetworkProtocolAttribute> AllProtocols { get; }
= new List<NetworkProtocolAttribute> {
FTP,
LPD,
// and so on...
}.AsReadOnly();
但是,除非你有一些具体的要求,否则我只会使用普通的枚举。
https://codereview.stackexchange.com/questions/220484
复制相似问题