清楚地确定给定枚举元组的动作

时间:2016-12-01 15:37:42

标签: c#

我正在尝试确定最干净的(如果可以很容易理解的话,那就足够了)确定在给定元组列表时要执行哪些操作的方法。
让我们说我有MyType表和MyAction表。这些表由中间表ActionsPerType连接,因为MyType与MyAction具有多对多关系。

现在,我们的想法是执行ActionsPerType声明的操作,例如:

Dictionary<int, int> actionsPerType = context.ActionsPerType
    .GroupBy(c => c.MyTypeId)
    .ToDictionary(c => c.Key.MyTypeId, c.ToList());

我想将其转换为Dictionary<int, Func<Task<decimal>>>,其中KeyactionsPerType.KeyValue是代码中定义的async Task<decimal>列表。

是否有更清洁的方法比这样(在这里完成,未经测试):

foreach (var item in actionsPerType)
{
    switch ((MyTypeEnum)item.Key)
    {
        case MyTypeEnum.Random:
        {
            foreach (var action in actionsPerType[MyTypeEnum.Random])
            {
                switch ((MyActionEnum)action)
                {
                    case MyActionEnum.Random:
                        dictionary[MyTypeEnum.Random].Add(SomeTaskThatReturnsBool);
                        break;
                }
            }
        }
    }
}

MyTypeEnum将保留大约10个项目,而MyActionEnum将保持在25附近,所以这将是非常漫长和丑陋的。

2 个答案:

答案 0 :(得分:1)

就个人而言,我是属性的忠实粉丝。我不完全确定预期的结果,如果以下情况适合您的情况,但现在就去了。

因为enum被认为是常量,所以它们可以在属性参数中使用。因此,以下是可能的:

public enum TypeEnum{
    T1,T2
}

public enum ActionEnum{
    A1,A2
}

public static class SomeClass
{
    [TypeAction(TypeEnum.T1, ActionEnum.A1)]
    public static void Foo(){
    }

    [TypeAction(TypeEnum.T1, ActionEnum.A2)]
    [TypeAction(TypeEnum.T2, ActionEnum.A2)] //<-- example of method can be used for multiple types/actions
    public static void Bar(){
    }
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] // <- AllowMultiple in case an action can be used multiple times
public class TypeActionAttribute:Attribute
{   
    public TypeActionAttribute(TypeEnum type, ActionEnum action)
    {
        this.Type=type;
        this.Action = action;           
    }

    public TypeEnum Type{get;set;}
    public ActionEnum Action{get;set;}
}

创建属性类后,可以将每个枚举组合分配给任何方法。获取所有方法可以在运行时完成(最好在初始化期间执行一次并记忆)。 从长远来看,可能的组合列表可能是最有用的,但是您的示例似乎只需要TypeEnum所有方法(ActionEnum不存储在pseudecode中),这类似于:

var typeMethods = (from m in typeof(SomeClass).GetMethods() //the methods are probably based in multiple types. Depending where they can be found, the types of an Assembly can be queried
            from a in m.GetCustomAttributes(typeof(TypeActionAttribute), true)              
            group m by ((TypeActionAttribute)a).Type)
            .ToDictionary(gr=>gr.Key, gr=>gr.ToList());

typemethods将是TypeEnum的字典,其中包含methodinfo&s的列表。 (methodinfos可以被调用或处理为特定的lambdas)

答案 1 :(得分:0)

我非常喜欢@ Me.Name给出的答案。但是,如果由于一些奇怪的原因,属性不是一个选择,为什么不使用任务字典:

Dictionary<MyActionEnum, Func<Task<decimal>>> tasks = new Dictionary<MyActionEnum, Func<Task<decimal>>> {
                { MyActionEnum.A1, __Task1 },
                { MyActionEnum.A2, __Task2 },
                { MyActionEnum.A3, __Task3 },
                { MyActionEnum.A4, __Task4 },
                { MyActionEnum.A5, async () => { return await Task.Delay(5000).ContinueWith(result =>  new Decimal(16)); } }
            };
static async Task<decimal> __Task1() { return await Task.FromResult<decimal>(new Decimal(420)); }
// etc

如果我理解你的要求,那么这应该与linq完全吻合,我想这里的优点是字典允许运行时动态。