2013-10-29 33 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

相关问题