나는 이미 제안 된 사전 접근법의 변형을 보여주고 싶습니다. 이 솔루션을 기반으로 다음을 수행 할 수 있습니다.
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)이 속성에 정의되어 자신의 ID로 JobDoer
인스턴스를 검색 할 수있는 JobDoerFactory
정의 다음 BuildCache
방법에서
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.
}
}
을, 당신은 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;
}
이 코드를 테스트하지 않았다, 그래서 컴파일 나도 몰라,하지만 난 몇 년 프로젝트에이 메커니즘을 사용했다. 이렇게하면 사전에 연결하지 않고도 새 클래스를 쉽게 정의 할 수 있습니다. 런타임시 자동으로 수행됩니다.
과도한 것처럼 보일 수도 있지만, +2000 JobDoer
클래스를 사용하면 많은 도움이됩니다.
업데이트 : JobDoerAttribute
의 아이디어가 마음에 들지 않으면 추상 JobDoer
클래스의 추상 속성으로 구현할 수도 있습니다. 그러나 속성을 사용하면 코드가 매우 명확하고 표현력이 풍부합니다.
"그들 중 하나를 찾아야합니다"는 의미는 무엇입니까? 메시지에서 GUID를 찾는 방법은 무엇입니까? 그것이 당신의 질문의 요점입니까? – Seb
@Seb : 아니, 메시지와 함께 전달 된 GUID가 있지만 내 목록에 동등한 GUID가 있어야합니다 (실제 목록이 없습니다). – Behrooz
현재, 나는 대표자 (세계에서 가장 느린 것) 애호가들로부터 세 가지 대답을 가지고 있습니다. – Behrooz