기본적으로 CommandNExcecutor
유형을 CommandN
유형으로 매핑해야합니다.
1) 사전을 사용하십시오. 이것은 가장 쉬운 방법입니다.
private static readonly Dictionary<Type, Type> map = new Dictionary<Type, Type>
{
{ typeof(Command1), typeof(Command1Executor) },
{ typeof(Command2), typeof(Command2Executor) },
...
};
List<CommandResult> Execute(List<CommandBase> commands)
{
return commands
.Select(command =>
{
var executor = Activator.CreateInstance(map[command.GetType], command);
return executor.Execute();
})
.ToList();
}
2) 메타 데이터 (속성)를 사용하십시오. 이 기능은 핵심 기능을 다시 빌드하지 않고 명령 유형을 동적으로 추가 할 수있는 플러그인 기반 시나리오에 적합합니다. 그것은 당신 자신의 구현 일 수도 있고 기존 DI 컨테이너 구현 일 수도 있습니다 (대다수는 메타 데이터 API를 공개합니다).
[AttributeUsage(AttributeTargets.Class)]
public sealed class CommandExecutorAttribute : Attribute
{
public CommandExecutorAttribute(Type commandType)
{
CommandType = commandType;
}
public Type CommandType { get; }
// ...
}
[CommandExecutor(typeof(Command1))]
public sealed class Command1Executor : ICommandExecutor
{
// ...
}
List<CommandResult> Execute(List<CommandBase> commands)
{
return commands
.Select(command =>
{
// obtain executor types somehow, e.g. using DI-container or
// using reflection;
// inspect custom attribute, which matches command type
var executorType = ....
var executor = Activator.CreateInstance(executorType , command);
return executor.Execute();
})
.ToList();
}
UPDATE.
당신은 반사를 피하기 첫 번째 경우에 단지 Func<CommandBase, ICommandExecutor>
에 사전에 값을 입력 매개 변수를 바꾸려면 :
var executor = map[command.GetType](command);
:
private static readonly Dictionary<Type, Func<ICommandExecutor>> map = new Dictionary<Type, Func<ICommandExecutor>>
{
{ typeof(Command1), command => new Command1Executor(command) },
{ typeof(Command2), command => new Command2Executor(command) },
...
};
이 대신 반사의 위임을 통해 집행을 만들 수 있습니다
두 번째 경우 은 반사를 완전히 피할 수 없습니다. 실행자 유형을 어떻게 든 가져와야하기 때문입니다. 그러나 사례 1 (사전 포함)로 이어질 수 있습니다.
게으른
map
확인 :
private static readonly Lazy<Dictionary<Type, ConstructorInfo>> map = ...
그런 다음, Lazy<T>
초기에, 모든 반사 작업을 수행. 이 번호는 static Lazy<T>
이므로 앱 도메인별로 한 번 수행합니다. ConstructorInfo
전화는 충분히 빠릅니다. 따라서 첫 번째 명령을 처리 할 때 한 번만 성능이 저하됩니다.
경우 2에 대한 또 다른 옵션은 (그들은 모두 Lazy<Dictionary>
가정)입니다
대신
ConstructorInfo
을 반영
- ,
ConstructorInfo
를 사용하여 Expression<Func<CommandBase, ICommandExecutor>>
의 구축을 컴파일하고 사전에 대표단을 넣어 -이의 대리인과 동일합니다 case 1이지만 동적으로 지원되는 명령 유형;
- IL을 방출하여 종속성을 생성하는 DI 컨테이너를 사용합니다 (AFAIK, NInject).
- 자신을 내 보냅니다 (IMO, 이것은 바퀴를 완전히 발명 할 것입니다).
그리고 마지막으로,이 가장 쉬운 방법 해결 는 측정 성능, 는 더 복잡한 방법을 고려한다. 조숙 한 최적화를 피하십시오. 나는 당신이 자연을 명령하는 것에 대해서는 아무 것도 모른다. 그러나 그 명령 실행은 보다 길다. 뭔가를 반영하는 것보다 길다. 물론 나는 틀렸다는 것을 알 수있다.
희망이 도움이됩니다.
명령 유형에 따라 키가 사전에 (을 만들거나 functons) 모든 명령 집행을 넣습니다. 이렇게하면 다른 체인이 필요하지 않습니다. – Evk