1

我正在为 REST API 编写一个包装器。因此,每当我从服务器检索项目时,我只需要使用参数(在 uri 中)。我现在这样做的方式效果很好,但我只是觉得必须有另一种优雅的方式来做到这一点,也许是enum什么。

我不喜欢我需要“知道”选项是什么,因为Dictionary类型是string。我试过了Dictionary<EnumType, string>,但我有不止一种类型的enum. 另外,我不确定如何将EnumType(键)映射到适当的值。

基本上,我尽量避免使用魔法关键字。

这是我的部分代码:

public string GetUnreadItems()
{
    var options = new Dictionary<string, string>();
    options.Add("ItemType", "Unread");
    options.Add("SortBy", "Latest");
    // GetItemsBasedOn(options);
}

public string GetAllItems()
{
    var options = new Dictionary<string, string>();
    options.Add("ItemType", "All");
    // GetItemsBasedOn(options);
}

public string GetItemsBasedOn(Dictionary<string, string> options)
{
    // Do request here based on options passed
    // and return the result to caller function 
}

编辑:这就是我想要实现的http://getpocket.com/developer/docs/v3/retrieve

我想实现选项sortdetailTypecontentTypeFavoriteState。每个选项都有自己的选项,但一次只能选择一个。

4

1 回答 1

2

有几种方法可以用来改进当前的设计。我不同意我将要向您介绍的解决方案是理想的解决方案,但鉴于您已经确定要使用的解决方案,enum我认为您会对此解决方案感到满意。

您可以做的是定义一个enum带有[Flags]属性的标记。为枚举中的每个标志分配一个值,该值是 2 的幂。如果您想组合选项以创建单个选项,请按位使用,或者就像我在前面的示例中使用名为“All”的标志所做的那样:

[Flags]
public enum GetItemOptions
{
    Read = 0x1,
    Unread = 0x2,
    All = 0x1 | 0x2,
    SortByOldest = 0x4,
    SortByLatest = 0x8
}

从您的代码示例中,第一个调用现在看起来像这样:

GetItemsBasedOn(GetItemOptions.Unread | GetItemOptions.SortByLatest);

第二个看起来像这样:

GetItemsBasedOn(GetItemOptions.All);

为了启用此设计,您需要调整GetItemsBasedOn方法签名,以便它指定GetItemOptions枚举类型的参数。以下是如何处理不同设置的示例。

public static void GetItemsBasedOn(GetItemOptions getItemOption)
{
    if (getItemOption.HasFlag(GetItemOptions.SortByOldest) && getItemOption.HasFlag(GetItemOptions.SortByLatest))
        throw new ArgumentException("I can't sort by both...");

    if (getItemOption.HasFlag(GetItemOptions.Read))
    {
        Console.WriteLine("READ");
    }

    if (getItemOption.HasFlag(GetItemOptions.Unread))
    {
        Console.WriteLine("UNREAD");
    }

    if (getItemOption.HasFlag(GetItemOptions.SortByOldest))
    {
        Console.WriteLine("SORT BY OLDEST");
    }
    else if (getItemOption.HasFlag(GetItemOptions.SortByLatest))
    {
        Console.WriteLine("SORT BY NLATEST");
    }
}

Enum.HasFlag我认为您对按位操作了解不多,因此我通过使用仅检查给定GetItemOptions枚举是否指定了标志的方法来尽可能简化代码示例。

RegexOptions Enumeration在使用或之前,您可能已经见证过这种模式ControlStyles Enumeration

更新

我建议您enum为每个参数创建一个并定义一个像这样的类:

public class PocketDataRequest
{
    public State? State { get; set; }
    public Favourite? Favourite { get; set; }
    public ContentType? ContentType { get; set; }
    public Sort? Sort { get; set; }
    public DetailType? DetailType { get; set; }

    public Dictionary<string, string> ToPostData()
    {
        return GetType().GetProperties()
                        .Where(p => p.GetValue(this, null) != null)
                        .ToDictionary(p => p.Name, 
                                      p => p.GetValue(this, null).ToString());
    }
}

这将利用以下语法:

PocketDataRequest pocketDataRequest = new PocketDataRequest();
pocketDataRequest.State = State.Unread;
pocketDataRequest.Sort = Sort.Newest;
GetItemsBasedOn(pocketDataRequest.ToPostData());

在我的实现ToPostData方法中,我使用 LINQ 和反射,那只是因为我很懒。您需要手动评估每个enum值,特别是如果您想将enum名称更改为更合适的名称。此外,如果您尝试传递名为 的参数,我的代码将失败favorite。这是因为favorite取数字“0”或“1”。这不是一个大问题,因为你可以做的事情是这样定义的enum

public enum Favourite
{
    UnfavouritedItems = 0,
    FavouritedItems = 1
}

然后简单地转换该值(Int32)并将该值添加到Dictionary<string, string>or NameValueCollection

于 2013-04-20T17:27:07.247 回答