2013-10-29 57 views
0

考慮在.NET框架中使用類層次結構定義的名稱空間。反思可以覆蓋基類中的虛函數

namespace OfficialDotnetNS 
{ 

    namespace officialNS.Bases 
    { 
     public class BaseOfA : IFakeA, IFakeB 
     { 
      protected void Driver(Stream stream){ this.DriveFoo(stream); }; 
      protected internal virtual void DriveFoo(Stream stream); 
     } 
    } 

    public abstract class A : officialNS.Bases.BaseofA 
    { 
     protected internal override void DriveFoo(Stream stream){ this.Foo(stream); }; 

     protected virtual void Foo(String stream); 
    } 

    public class B : A {} 

    public class C : A {} 

    public class D : A {} 

    // and 50+ similar classes derived from A 
} 

我有一個BaseofA對象和當我打電話Driver(stream)它隨後調用的AFoo和合適的派生類的。

現在,我要重寫Foo()相同的代碼,所以從A繼承該自定義實現派生的所有類。

一種方法是編寫自定義包裝爲每個類:

public class CustomB : B 
{ 
    protected override void Foo(Stream stream) 
    { 
     stream.Position = 12; 
     base.Foo(stream); 
    } 
} 

public class CustomC : C 
{ 
    protected override void Foo(Stream stream) 
    { 
     stream.Position = 12; 
     base.Foo(stream); 
    } 
} 

public class CustomD : D 
{ 
    protected override void Foo(Stream stream) 
    { 
     stream.Position = 12; 
     base.Foo(stream); 
    } 
} 

//.. for all 50+ classes 

我們能做到這一點使用反射或不重複的代碼一些其他的技術?

回答

1

是的。它被稱爲代理,它是由實體框架使用的技術。有幾種方法可以實現這一點,但IMO最好的是CastleProject DynamicProxy

例如(簡化的情況,但我認爲這你想要做什麼):

void Main() 
{ 
    var pg = new Castle.DynamicProxy.ProxyGenerator(); 
    var typeA = typeof(A); 
    var interceptor = 
     new FooInterceptor(
      str => Console.WriteLine("intercepted {0}", str)); 
    IEnumerable<A> objs = Assembly 
     .GetExecutingAssembly() 
     .GetTypes() 
     .Where(t => t.IsSubclassOf(typeA)) 
     .Select(t => (A)(pg.CreateClassProxy(t, interceptor))); 

    foreach(A a in objs) 
    { 
     a.CallFoo("hello world"); 
    } 
} 

public class A 
{ 
    public void CallFoo(string someString){ 
     Foo(someString); 
    } 
    protected virtual void Foo(string someString) 
    { 
     Console.WriteLine("base Foo {0}", someString); 
    } 
} 
public class B : A {} 

public class C : A {} 

public class D : A {} 

public class FooInterceptor : IInterceptor 
{ 
    Action<string> interceptorDelegate; 
    public Interceptor(Action<string> interceptorDelegate) 
    { 
     this.interceptorDelegate = interceptorDelegate; 
    } 
    public void Intercept(IInvocation invocation) 
    { 
     var isFooCall = invocation.Method.Name == "Foo"; 
     if(isFooCall) 
     { 
      interceptorDelegate 
       .Invoke((string)(invocation.Arguments[0])); 
     } 
     else 
     { 
      invocation.Proceed(); 
     } 
    } 
} 
+1

你可以指出DynamicProxy的特定功能,專注於衝壓的覆蓋功能,所有*兄弟班*? – Annie

+0

@Annie:我添加了一些代碼來演示。 – spender

+0

謝謝,它清除了幾乎所有的東西。只是有點好奇心。我試圖調用'BaseOfA'類的'DriverFoo',它最終會''A'類的'Foo'。在你的例子中,如果'A'有一個父類,你將如何從A的基地選擇A的子女? – Annie

相關問題