저는 입력 및 출력을 제어하기 위해 간단한 플러그인 아키텍처를 사용하는 C# (현재 3.5이지만 필요에 따라 다른 버전에도 적용 할 수있는 가능성이 높습니다)로 프로그램을 작성하고 있습니다. 각 플러그인은 사용자가 사용할 플러그인을 선택할 때로드되는 DLL입니다.C# Generic Method vs Casting
실제 플러그인 클래스는 런타임까지 알 수 없으므로 래퍼 클래스에서 리플렉션을 사용하여 플러그인의 메소드 및 액세스 속성을 호출합니다.
지금까지, 나는 플러그인에서 메소드를 호출하려면 다음을 사용하고 :
public object Method(string methodName, params object[] arguments) {
// Assumed variables/methods/exceptions:
// Dictionary<string, MethodInfo> Methods: a cache of MethodInfo's
// of previously called methods.
// NoSuchMethodException: thrown if an unknown/unreachable method is
// requested. The message member contains the invalid method name
// void LoadMethod(string methodName, params object[] arguments): responsible
// for retrieving the MethodInfo's, or throw a NoSuchMethodException
// object Plugin: an instance of the dynamically loaded class.
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
return Methods[methodName].Invoke(Plugin, arguments);
}
처럼 사용되는이 발신자만큼, 잘 작동
string[] headers = (string[]) Plugin.Method("GetHeaders", dbName, tableName);
올바른 반환 값을 유형으로 캐스팅합니다. 플러그인은 특정 인터페이스를 구현해야하므로 호출자는이 유형을 알아야합니다.
그러나 반사와 약간의 추가 작업을 수행 한 후, 다음과 같은 다른 형태 나에게 발생
public T Method<T>(string methodName, params object[] arguments) {
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (Methods[methodName].ReturnType != typeof(T)) {
// Could also move this into LoadMethod to keep all the throwing in one place
throw new NoSuchMethodException(methodName);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
return (T) Methods[methodName].Invoke(Plugin, arguments);
}
이 하나처럼 사용됩니다
string[] headers = Plugin.Method<string[]>("GetHeaders", dbName, tableName);
이 버전은 기본적으로 방법으로 캐스팅 이동 방법. 호출자는 분명히 예상되는 반환 유형을 알아야하지만, 항상 그렇습니다. 그것은 무효 방법이 작동하지 않습니다,하지만 난 그것을위한 방법의 버전을 포함 할 수 있습니다 : 내 질문은
public void Method(string methodName, params object[] arguments) {
// Good for void methods, or when you're going to throw away the return
// value anyway.
if (!Methods.ContainsKey(methodName)) {
LoadMethod(methodName, arguments);
}
if (arguments != null && arguments.Length == 0) {
arguments = null;
}
Methods[methodName].Invoke(Plugin, arguments);
}
을 - 다음 중 하나를 다른 것보다 본질적으로 더 나은 (의 주어진 값에 대해 '더 나은') ? 예를 들어, 주목할 만하게 빠릅니다. 더 쉽게 이해할 수 있을까요? 더 많은 지원이 있습니까?
저는 개인적으로 후자의 모습을 좋아하지만, 제 귀환 유형 테스트 (Methods[methodName].ReturnType != typeof(T)
)가 너무 단순 할 수도 있다고 조금 걱정합니다. 흥미롭게도 원래는 !(Methods[methodName].ReturnType is T)
이었지만 항상 실패한 것 같습니다.
내가 찾을 수있는 가장 가까운 기존 질문은 Generic method to type casting이고 일부 답변은 후자의 방법이 전자보다 비용이 많이들 것이라고 제안했지만 세부적인 방법은별로 없습니다 (질문이 많을수록 그보다는 더 나은 방법의 구현).
설명 : 이것은 IPlugin을 사용하지 않고 손으로 만져서 매우 제한된 플러그인 시스템입니다. 제네릭 메서드가 호출자가이 상황에서 사용할 것을 기대하는 것보다 본질적으로 더 좋고/더 나쁜지에 대한 질문에 더 관심이 있습니다.
음 모두 같은 일을하는 것처럼 보입니까? 하나는이 방법으로 주조하고 다른 하나는 외부에 주조합니까? – lahsrah
플러그인의 구현 세부 정보를 사용하는 이유는 무엇입니까? – ChaosPandion
@sylon 나는 둘 다 똑같은 일을하고 있음을 안다. 나의 질문은 어떤 것이 더 좋은가라는 것이다. – MDB