2013-05-16 4 views
3

저는 나를 위해 객체를 만들고 설정하는 라이브러리를 가지고 있습니다. 그런 다음 객체를 사용하여 객체를 사용할 수 있습니다.C#은 메소드/필드를 객체에 오버라이드/추가합니다.

, 내가 때문에 클래스의 코드를 변경하지 않으의 내가 "A"는

그래서 내가 그 특정 객체의 메소드를 오버라이드 (override) 할 클래스의 객체 "는"주어진있어 가정 해 봅시다 라이브러리 변경이 필요합니다.

루비에서 내가 할 수있는 그런 식으로, 싱글 톤 클래스를 사용하여 : 지금은 C#으로 동일한 작업을 수행 할 수있는 방법

class FirstClass 
    def test 
     p "test" 
    end 
end 

o = FirstClass.new 

class << o 
    def test 
     p "overridden" 
    end 
    def extraMethod 
     p "ok" 
    end 
end 

o.test # prints "overridden" 
o.extraMethod 

?

업데이트

내가 제출 한 대답을 사용하지 않는 결국

너무 추한과 그들을 따라서 파생 클래스에 존재하게 보호하거나 공개하는 중 기본 클래스의 모든 개인 필드를 변경해야하기 때문에 기본에서 파생 값을 복사 할 수 있습니다.

나는 도서관에 기본 클래스에서 파생 된 유형을 통과하고 사용하여 인스턴스를 생성하도록 라이브러리를 변경하는 것입니다 사용 결국 방법 :

(A)Activator.CreateInstance(mytype, arguments); 
+0

무엇을 원하십니까? 그것은 말이되지 않습니다. –

답변

4

C#을하지 않는 (직접) 지원 런타임 유형의 확장 (dynamic 메커니즘을 통한 경우 제외).

가장 가까운 옵션은 가능성이 dynamicExpandoObject을 사용하는 것입니다 :

말했다되고 그건
dynamic o = new ExpandoObject(); 
o.a = 10; 

o.ExtraMethod = new Action(() => Console.WriteLine("ok")); 

// Invoke 
o.ExtraMethod(); 

이 C#을 작동하는 일반적인 방법은 아니다. 런타임 (따옴표 통지) "메소드를 오버라이드 (override)"을

1

Delegates

public class SomeClass 
{ 
    public SomeClass() 
    { 
     //set the default 
     OverridableMethod =() => MessageBox.Show("Default!"); 
    } 

    public void StandardMethod() 
    { 
     //Call it. 
     OverridableMethod(); 
    } 

    public Action OverridableMethod {get;set;} 
} 

사용을 사용하여 C#에서 가능하다 :

var some1 = new SomeClass(); 
some1.StandardMethod(); //Shows "Default!" 
some1.OverridableMethod(); //Shows "Default!" 

var some2 = new SomeClass {OverridableMethod =() => MessageBox.Show("Override!!")}; 
some2.StandardMethod(); //Shows "Override!" 
some2.OverridableMethod(); //Shows "Override!" 
+0

감사하지만 기본 코드를 변경해야합니다. –

+0

@SpaceMonkey 이러한 종류의 확장 성이 필요한 경우 초기 코드를 작성할 때이를 고려해야합니다. 지금은 주위에 방법이 없습니다. –

0

실제로이 작업을 수행하는 추한 방법이있다.

나는 상속 및 다운 캐스팅을 사용할 생각 이었지만 다운 캐스팅은 유효하지 않습니다. 그러나 리플렉션을 사용하여 동일한 결과를 얻을 수 있습니다.

static void Main() 
     { 
      A a = new A(); 
      a.FieldA = 999; // change the object 
      a.test(); // "This is A and FieldA is 999" 

      //B b = (B)a; // => Error: Invalid you cannot downcast ! 

      // using reflection we turn "a" into an instance of B that is a copy of the old "a" 
      a = new B(a); 
      a.test(); // This will call the method in B: "Calling the new method" "This is B and FieldA is 999 and FieldB is 10" 

      // a.newMethod(); => Error cannot access this method because "a" is declared as an instance of A (even though it's actually of B now) 

      B b = (B)a; // Now downcasting works fine (because A is an instance of B actually) 

      b.newMethod(); // works as expected: "This is B and FieldA is 999 and FieldB is 10" 
     } 



     class A 
     { 
      public int FieldA; 

      public A() 
      { 
       FieldA = 100; 
      } 

      virtual public void test() 
      { 
       Console.WriteLine("This is A and FieldA is {0}", FieldA); 
      } 
     } 

     class B : A 
     { 
      int FieldB; 
      public B(A a) 
      { 
       // copy all fields 
       foreach (FieldInfo pi in typeof(A).GetFields()) 
        GetType().GetField(pi.Name).SetValue 
         (this, pi.GetValue(a)); 

       // add this field: 
       FieldB = 10; 
      } 

      // We can override methods 
      override public void test() 
      { 
       Console.WriteLine("Calling the new method:"); 
       newMethod(); 
      } 

      // Add a new method but it will only be visible after casting A to B 
      public void newMethod() 
      { 
       Console.WriteLine("This is B, FieldA is {0} and FieldB is {1}", FieldA, FieldB); 
      } 
     } 

그래서 "a"내의 메소드를 오버라이드하고 새 필드를 추가했습니다.

Ruby에서 할 수있는 것과 같은 것을 얻을 수는 없다는 것을 알지만 최소한 재정의 할 수있는 메소드 내에서 사용할 수있는 메소드/필드를 메서드를 오버라이드하고 추가 할 수 있습니다.

+0

매우 못 생기고 쓸모없는 (생각합니다) 일을하는 방식입니다. 기본 클래스에 재정의 할 가상 메서드가없는 경우 유일한 방법은 확장 메서드를 사용하는 것입니다.기본 클래스를 수정할 수 없으면 빈 구현으로 가상 메소드로 직접 메소드를 넣으십시오. – MikeSW

+1

@MikeSW 확장 메서드는 재정의 할 수 없습니다. –

+0

메서드를 재정의 할 수 없을 때 확장 메서드는 ADD 동작을위한 유일한 방법입니다. – MikeSW