【问题标题】:Reflection to override virtual function in base class反射以覆盖基类中的虚函数
【发布时间】:2013-10-29 02:42:30
【问题描述】:

考虑在 .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 

我们可以使用反射或其他一些技术来做到这一点而无需重复代码吗?

【问题讨论】:

    标签: c# reflection inversion-of-control


    【解决方案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();
            }
        }
    }
    

    【讨论】:

    • 您能否指出 DynamicProxy 的具体功能,它专注于为所有 兄弟类 标记覆盖函数?
    • 谢谢,它几乎可以清除所有内容。只是有点好奇。我正在尝试调用BaseOfA 类的DriverFoo,它最终将是A 类的Foo。在您的示例中,如果 A 有一个父类,您将如何从 A 的 Base of A 中选择 A 的子级?
    猜你喜欢
    • 2014-08-16
    • 2017-09-22
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    相关资源
    最近更新 更多