2012-12-12 4 views
4

3 가지 오버로드 된 메소드가있는 클래스가 있습니다.C# - 모든 메서드 인수를 다른 메서드로 전달?

class MyChildClass 
{ 
    public void myMethod(int i) 
     { /* do something with i */ } 
    public void myMethod(int a, string b) 
     { /* get i from a and b and call: */ myMethod(i); } 
    public void myMethod(string c, string d) 
     { /* get i from c and d and call: */ myMethod(i); } 
} 

가 지금은 다른 (부모) 클래스의 private 필드가이 클래스를하고 싶습니다,하지만 난에 액세스 할 수 있도록하는 세 가지 방법이 필요합니다의 말합시다있다. 지금은 방금했습니다 :

class MyBaseClass 
{ 
    private MyChildClass myObject = new myChildClass(); // or similar 
    public void myMethod(int i) 
     { myObject.myMethod(i); } 
    public void myMethod(int a, string b) 
     { myObject.myMethod(a, b); } 
    public void myMethod(string c, string s) 
     { myObject.myMethod(c, d); } 
} 

하나의 짧은 방법으로 구현하는 방법이 있습니까? 같을 것이다 뭔가 :

public void myMethod(unknownListOfArgumentsOfDifferentTypes args) 
    { myObject.myMethod(args); } 

나는 public void myMethod(params object[] something)를 사용하려했지만 작동하지 않았다. 가능합니까, 아니면 모든 방법을 다른 방식으로 "프로젝트"해야합니까?

EDIT : 하위 클래스에는 다양한 메소드와 필드가 있으며, 상위 클래스에서만 액세스 할 수 있습니다. 그래서 부모님이 그 후에 파생되기를 원하지 않습니다. 나는 설명하지 않았다. 미안 자식 클래스가 그 세 가지 방법만을 포함하는 것처럼 보인다면 말이다. 그것들은 부모 클래스의 퍼블릭 메소드로서 접근 가능하게하고 싶습니다. 당신은 당신이거야 반사를 사용하여 일반적인 외관의 일종을 구현하는 경우

+7

하지 마십시오. 그러한 코드를 작성하면 새끼 고양이가 죽습니다. –

+0

이미하고있는 것처럼해야합니다. –

+0

http://www.codeproject.com/Articles/5511/Dynamic-Proxy-Creation-Using-C-Emit은 올바른 방향으로 당신을 가리킬 수도 있습니다 – sroes

답변

1

당신은 같이 public void myMethod(params object[] something)를 사용할 수 있습니다

public static void Main() 
{ 
    UnknownArgumentsMethod1(1, 2, 3, "foo"); 
} 

public static void UnknownArgumentsMethod1(params object[] list) 
{ 
    UnknownArgumentsMethod2(list); 
} 

public static void UnknownArgumentsMethod2(params object[] list) 
{ 
    foreach (object o in list) 
    { 
     if (o.GetType() == typeof(int)) 
     { 
      Console.WriteLine("This is an integer: " + (int)o); 
     } 
     else if (o.GetType() == typeof(string)) 
     { 
      Console.WriteLine("This is a string: " + (string)o); 
     } 
    } 
} 
+0

나는 그것이 내가 달성하기를 원했던 것에 가장 가깝기 때문에 대답으로 표시했습니다. 불행히도 코드를 살펴보면 자식의 모든 메서드에 대해 부모 메서드에서 하나를 사용하는 것이 덜 복잡하며 새로운 "범용"메서드에서 매개 변수의 형식을 검사하는 것보다 빠릅니다. 틀 렸으면 고쳐줘. – WRonX

+0

수신 된 인수를 전달하려는 많은 메소드가있는 경우 더 빠르지 만 더 성 가해 야합니다. – sohil

+0

@WRonX, 여러 메소드의 서명이 같고 이름 만 다른 경우 어떻게됩니까? – Jodrell

2

class MyChildClass : MyBaseClass 
{ 
} 

같은 효과, 적은 코드,이 방법을하지 않는 이유는 MyChildClassMyBaseClass


입니다 형식 안전성의 이점을 우회하고 문제 발견을 지연시키는 것만으로 성능을 저하시킬 수 있습니다.

당신은 또한 당신의 클래스 이름과 부합하지 않는 "is a"관계가 있습니다.


당신이 사용이 게시물에 받아 들여진 GetMethodBySig 확장을 만들 수있는 관련 혜택이 simplicty을 포기하려는 경우

. 이 같은

뭔가,

class SemiGenericFacade<T> where T : new() 
{ 
    private readonly t = new T(); 

    public void CallVoidOnT(string name, params object[] parameters) 
    { 
     var paramTypes = parameters.Select(p => typeof(p)) 

     var match = typeof(T).GetMethodBySig(typeof(void), paramTypes) 
      .Single(mi => mi.Name == name); 

     match.Invoke(this.t, parameters); 
    } 
} 

구현 및 호랑이로 전환 고양이이 Methods를 사용하여 그녀의 새끼 고양이를 먹고, 표트르 저스티의 발언에 이어. 당신은 다음과 같이 사용할 수있는 링크 확장

public static class Extensions 
{ 
    public static MethodInfo GetMethodByNameThenSig(
     this Type type, 
     string name, 
     Type returnType, 
     params Type[] parameterTypes) 
    { 
     return type.GetMethods().Where((m) => 
     { 
      if (m.Name != name) 
      { 
       return false; 
      } 

      if (m.ReturnType != returnType) 
      { 
       return false; 
      } 

      var parameters = m.GetParameters(); 
      if ((parameterTypes == null || parameterTypes.Length == 0)) 
      { 
       return parameters.Length == 0; 
      } 

      if (parameters.Length != parameterTypes.Length) 
      { 
       return false; 
      } 

      for (int i = 0; i < parameterTypes.Length; i++) 
      { 
       if (parameters[i].ParameterType != parameterTypes[i]) 
       { 
        return false; 
       } 
      } 

      return true; 
     }).Single(); 
    } 
} 

에 추가하는 것이 나을이 작업을 수행하는 경우


,

class GenericFacade<T> where T : new() 
{ 
    private readonly t = new T(); 

    public void CallOnInternal(string name, params object[] parameters) 
    { 
     var paramTypes = parameters.Select(p => typeof(p)) 

     var match = typeof(T).GetMethodByNameThenSig(
      name, 
      typeof(void), 
      paramTypes); 

     match.Invoke(this.t, parameters); 
    } 

    public TResult CallOnInternal<TResult>(string name, params object[] parameters) 
    { 
     var paramTypes = parameters.Select(p => typeof(p)) 

     var match = typeof(T).GetMethodByNameThenSig(
      name, 
      typeof(TResult), 
      paramTypes); 

     return (TResult)match.Invoke(this.t, parameters); 
    } 
} 

최종 편집

반사를 사용하고 유형 안전성 손실과 관련된 비용을 고려하기 위해 관련된 코드를 살펴보십시오. 나는 전통적인 방식으로 명시 적으로 "has-a"관계를 수립하는 것이 더 바람직하다고 제안한다.

+1

MyChildClass로 모델링 한 것이 실제로 MyBaseClass라는 것을 알고 있습니까? BAckgroundColor 속성과 클래스 'TextArea'를 가진'style' 클래스가 있고 BackgroundColor 속성을 노출하고 TextArea에서 내부적으로 스타일을 스타일'style' 형식으로 유지 한 다음 스타일에서 TextArea를 파생시키는 것이 이상 –

+0

@RuneFS는 다른 질문처럼 들립니다. – Jodrell

+0

@RuneFS : 바로 여기 있습니다. 상위 클래스 내에서만 하위 클래스 개체의 기능을 완전히 사용하고 일부 선택된 메서드 만 공개적으로 사용할 수있게하려고합니다. 나는 그 질문을 이미 더 분명하게 편집했다. – WRonX

1

확실한 대답은 상속을하는 것입니다.

당신의 경우 (클래스의 이름이 다른 것을 제안하더라도) 그것을하는 방법은 BaseClass에서 ChildClass를 상속하는 것이고 그러면 BaseClass를 통해 노출 된 ChildClass의 메소드를 가지게됩니다.

예 :

class MyBaseClass: MyChildClass 
{ 
} 

클래스가 관련되고 당신은 MyBaseClass에 MyChildClass의 인스턴스를 가지고 있지만 방법의 특정 세트를 표시 할 수 있습니다 만, 당신이 할 수있는 것을 다른 사람이 개인 제작하지 않음으로써 싶어하지 않는 경우 단지 지금처럼 필요한 필드 노출하는 인터페이스를 통해 MyChildClass 인스턴스를 노출된다

public class BaseClass 
{ 
    public IChildClass ChildClassInstance = new ChildClass(); 
} 

public class ChildClass : IChildClass 
{ 
    public void myMethod(int i) 
    { /* do something with i */ } 
    public void myMethod(int a, string b) 
    { /* get i from a and b and call: */ myMethod(i); } 
    public void myMethod(string c, string d) 
    { /* get i from c and d and call: */ myMethod(i); } 
} 

public interface IChildClass 
{ 
    void myMethod(int i); 
    void myMethod(int a, string b); 
} 

을 다음 당신은 당신이 기본 클래스의 인스턴스를 통해 노출 될 수 있도록 메소드만을 액세스 할 수 있습니다 :

0123을
BaseClass test = new BaseClass(); 
test.ChildClassInstance.myMethod(1); 
test.ChildClassInstance.myMethod(1,"test"); 
관련 문제