我喜欢展示其他人已经提出的字典方法的变体。在此解决方案的基础上,您可以执行以下操作。
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
类的抽象属性。但是,我发现使用属性可以使代码非常明确和富有表现力。