4

我有很多(+2000)个 GUID(在某个网络类中),我的程序在收到消息时必须找到其中一个并完成与之相关的工作。
积极的一点是我有一个硬代码生成器,但最快的方法是我的目标(我不知道如何实现它)。

我的代码应该做这样的事情:

switch(received guid)  
{  
case guid1: do job 1; break;  
case guid2: do job 2; break;  
case guid3: do job 3; break;  
case guid4: do job 4; break;  
....  
}  
4

6 回答 6

15

您可以使用 Guid 作为键和委托引用作为值来创建字典。这将确保快速查找。

于 2010-03-24T13:52:05.647 回答
9

创建一个完成工作的接口,然后实现 2000 个完成工作的类,每个类都知道自己的 guid。然后使用其 guid 作为键将类添加到字典中。然后,当您获得 guid 时,您在字典中查找对象并调用接口上的方法。

public interface IJobDoer
{
    void DoJob();
    Guid Guid{get;}
}

public class FirstJobType : IJobDoer
{
    void DoJob()
    {
     /// whatever...
    }
    Guid Guid { get{return "insert-guid-here";}}
}
于 2010-03-24T14:12:26.617 回答
6

使用将 Guid 映射到代表任务的委托或类的哈希表,例如Dictionary<Guid, Action>or Dictionary<Guid, Task>

于 2010-03-24T13:52:37.267 回答
4

ADictionary<Guid, JobDelegate>可能比 switch 语句更快。

但是您必须进行概要分析才能确定。

于 2010-03-24T13:52:40.747 回答
3

我喜欢展示其他人已经提出的字典方法的变体。在此解决方案的基础上,您可以执行以下操作。

1 定义一个基类:

public abstract class JobDoer
{
    public abstract void DoJob();
}

2 定义工作人员的装饰属性。

public sealed class JobDoerAttribute : Attribute
{
    JobDoerAttribute(string jobDoerId)
    {
        this.JobDoerId = new Guid(jobDoerId);
    }

    public Guid JobDoerId { get; private set; }
}

3 定义使用该属性修饰的实际作业者类。例如:

[JobDoer("063EE2B2-3759-11DF-B738-49BB56D89593")]
public sealed class SpecificJobDoer : JobDoer
{
    public override void DoJob()
    {
        // Do a specific job
    }
}

4 定义一个JobDoerFactory允许JobDoer按其 ID 检索实例的属性,因为它在属性中定义:

public static class JobDoerFactory
{
    static Dictionary<Guid, JobDoer> cache;

    static JobDoerFactory()
    {
        // Building the cache is slow, but it will only run once 
        // during the lifetime of the AppDomain.
        cache = BuildCache();
    }

    public static JobDoer GetInstanceById(Guid jobDoerId)
    {
        // Retrieving a JobDoer is as fast as using a switch statement.
        return cache[jobDoerId];
    }

    private static Dictionary<Guid, JobDoer> BuildCache()
    {
        // See implementation below.
    }
}

在该BuildCache方法中,您可以JobDoer使用反射来加载实例。

private static Dictionary<Guid, JobDoer> BuildCache()
{
    // This is a bit naive implementation; we miss some error checking,
    // but you'll get the idea :-)
    var jobDoers =
       (from assembly in AppDomain.CurrentDomain.GetAssemblies()
        from type in assembly.GetTypes()
        where type.IsSubclassOf(typeof(JobDoer))
        let attributes =
            type.GetCustomAttribute(typeof(JobDoerAttribute), true)
        where attributes.Length > 0
        let attribute = attributes[0] as JobDoerAttribute
        select new { attribute.JobDoerId, type }).ToArray();

    var cache = new Dictionary<Guid, JobDoer>(jobDoers.Length);

    foreach (jobDoer in jobDoers)
    {
        // Note that actually a single instance of the job doer is
        // cached by ID. This means that every Job Doer must be 
        // thread-safe and usable multiple times. If this is not 
        // feasable, you can also create store a set of Func<JobDoer> 
        // objects that enable creating a new instance on each call.
        cache[jobDoer.JobDoerId] =
            (JobDoer)Activator.CreateInstance(jobDoer.type);
    }
    return cache;
}

这段代码我没有测试,所以不知道能不能编译,但是几年前我在一个项目中使用过这个机制。这种方式很容易定义新类,而不需要将它连接到一些字典。它在运行时自动完成。

这可能看起来有点矫枉过正,但如果你有 +2000JobDoer个课程,这会对你有很大帮助。

更新:请注意,如果您不喜欢 的想法JobDoerAttribute,您也可以将其实现为抽象JobDoer类的抽象属性。但是,我发现使用属性可以使代码非常明确和富有表现力。

于 2010-03-24T15:34:56.100 回答
0

创建一个带有 Guid 和 Action 的字典,然后搜索它。

于 2010-03-25T13:06:03.383 回答