我有一个便利类,它本质上是一个字典,它包含一个标记/值对列表,用于提交给API.
在最基本的层面上,我所做的就是:
enum Tag
{
Name, Date, //There are many more
}
class RequestDictionary : Dictionary<Tag, string>
{
}
Run Code Online (Sandbox Code Playgroud)
这很好地映射了API的需求,因为整个事件被发送并解析为字符串.然而,对于来电者来说并不是那么好; 例如,调用者必须知道如何Date正确格式化.
为了解决这个问题,我开始添加类型安全的特定于标签的属性.我将它们隔离在单独的界面中,这样它们就不会与普通的Dictionary属性混淆.
enum Tag
{
Name, Date
}
interface ITags
{
string Name { get; set; }
DateTime Date { get; set; }
}
class RequestDictionary : Dictionary<Tag, string>, ITags
{
public ITags Tags { get { return this; } }
string ITags.Name
{
get { return this[Tag.Name]; }
set { this[Tag.Name] = value; }
}
DateTime ITags.Date
{
get { return DateTime.ParseExact(this[Tag.Date], API_DATE_FORMAT, CultureInfo.InvariantCulture); }
set { this[Tag.Name] = value.ToString(API_DATE_FORMAT); }
}
}
Run Code Online (Sandbox Code Playgroud)
引入此接口后,调用者可以选择
dict[Tag.Date] = DateTime.Now.ToString(API_DATE_FORMAT);
Run Code Online (Sandbox Code Playgroud)
要么
dict.Tags.Date = DateTime.Now;
Run Code Online (Sandbox Code Playgroud)
后者对调用者的工作量较少,特别是因为API_DATE_FORMAT实际上是私有的.
我希望调用者能够使用对象初始化器语法:
var dict = new RequestDictionary
{
Tags.Date = DateTime.Now
}
Run Code Online (Sandbox Code Playgroud)
...但是这不会编译(错误是"无效的初始化成员声明符").
所以似乎调用者需要使用
var dict = new RequestDictionary
{
{ Tags.Date, DateTime.Now.ToString(API_DATE_FORMAT) }
};
Run Code Online (Sandbox Code Playgroud)
......这显然不是封装或方便的.
当您希望访问的属性是通过默认类接口中未包含的接口公开时,是否有任何方法可以使用对象初始化程序语法初始化对象?
以下代码可能会满足您的需求:
var dict = new RequestDictionary
{
Tags = { Date = DateTime.Now }
};
Run Code Online (Sandbox Code Playgroud)
关键是使用Tags = { Date(即一次下降一级)而不是Tags.Date =.
我承认该代码看起来不起作用,因为它看起来像是您正在分配给只读属性(即Tags)。但它确实有效(由于对象初始值设定项的工作方式)。