将对象初始化程序语法与接口一起使用

时间:2018-03-23 22:26:01

标签: c# .net interface

背景

我有一个便利类,它本质上是一个字典,它包含一个标记/值对列表,用于提交给API。

在最基本的层面上我所做的就是:

enum Tag
{
    Name, Date, //There are many more
}

class RequestDictionary : Dictionary<Tag, string>
{
}

这很好地映射了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); }
    }
}

引入此界面后,调用者可以选择

dict[Tag.Date] = DateTime.Now.ToString(API_DATE_FORMAT);

dict.Tags.Date = DateTime.Now;

后者对调用者的工作量较少,特别是因为API_DATE_FORMAT实际上是私有的。

问题

我希望调用者能够使用对象初始化器语法:

var dict = new RequestDictionary
{
    Tags.Date = DateTime.Now
}

...但是这不会编译(错误是“无效的初始化成员声明符”)。

所以调用者似乎需要使用

var dict = new RequestDictionary
{
    { Tags.Date, DateTime.Now.ToString(API_DATE_FORMAT) }    
};

......这显然不是很好的封装或方便。

当您要访问的属性是通过未包含在默认类接口中的接口公开时,是否有任何方法可以使用对象初始化程序语法初始化对象?

1 个答案:

答案 0 :(得分:3)

以下代码可能符合您的需求:

var dict = new RequestDictionary
{
    Tags = { Date = DateTime.Now }
};

关键是使用Tags = { Date(即一次降低一级)而不是Tags.Date =

我承认代码看起来像它不会起作用,因为看起来像你正在分配给只读属性(即{{1 }})。但它确实有效(由于object initializers work)。