开发者

fast way for finding GUIDs

开发者 https://www.devze.com 2022-12-24 04:26 出处:网络
I have lots(+2000) of GUIDs(i开发者_如何学运维n some network class) and my program must find one of them when it receives a message and do the job associated with it.

I have lots(+2000) of GUIDs(i开发者_如何学运维n some network class) and my program must find one of them when it receives a message and do the job associated with it.

the positive point is i have a hard-code generator, but the fastest way is my goal(and i don't know how to implement it).

my code should do something like this:

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;  
....  
}  


You could create a Dictionary with the Guid as the key and a delegate reference as the value. That would ensure fast lookups.


Create an interface for doing the Job, then implement 2000 classes which do the work, each of which knows its own guid. Then add the classes to a dictionary using its guid as the key. Then when you get the guid, you look the object up in the dictionary and call the method on the interface.

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

public class FirstJobType : IJobDoer
{
    void DoJob()
    {
     /// whatever...
    }
    Guid Guid { get{return "insert-guid-here";}}
}


Use a hashtable which maps Guid to a delegate or a class that represents the task, such as Dictionary<Guid, Action> or Dictionary<Guid, Task>.


A Dictionary<Guid, JobDelegate> would probably be faster than a switch statement.

But you would have to profile to be sure.


I like to show a variation of the dictionary approach others already proposed. Building on this that solution, you could do the following.

1 Define a base class:

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

2 Define a attribute for decoration of job doers.

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

    public Guid JobDoerId { get; private set; }
}

3 Define the actual job doer classes that are decorated with that attribute. For instance:

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

4 Define a JobDoerFactory that enables retrieving JobDoer instances by their Id as it is defined in the attribute:

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.
    }
}

In the BuildCache method, you can do the loading of JobDoer instances by using reflection.

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;
}

I didn't test this code, so I don't know if it compiles, but I used this mechanism in a project a few years back. This way it is easy to define new classes, without the need to hook it up to some dictionary. It is done automatically at runtime.

This might look a bit like overkill, but if you have +2000 JobDoer classes, this could help you a lot.

Update: Note that if you don't like the idea of the JobDoerAttribute, you can also implement it as abstract property on the abstract JobDoer class. However, I've found using an attribute makes the code very explicit and expressive.


Create a Dictionary with Guid And Action, and search over it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号