开发者

Method overloading: funnel call to derived class argument overload

Ok, I'm trying to do the following:

        protected bool ValidAdvert(Base item)
        {
            throw ThisIsAnAbstractClassException();
        }

        protected bool ValidAdvert(Derived1 item)
        {
            return ADerived1Spe开发者_Go百科cificPredicate;
        }

        protected bool ValidAdvert(Derived2 item)
        {
            return ADerived2SpecificPredicate;
        }    

And have the Derived class versions of the method be called, when a Base class is passed to the method. The base class is abstract so this should, in theory, be possible?

Before someone says something about overloading the method on the classes themselves, the logic inside the methods relies on a large number of different conditions, none of which are related, and none of which related to the Base/Derived class directly (such as login status, etc.)


If you find the double dispatch too intrusive, you can call the method by reflection and resolve the proper overload dynamically.

protected bool ValidAdvert(Base item)
{
    if (item.GetType() == typeof(Base))
        throw new ThisIsAnAbstractClassException();

    Type type = typeof(CurrentClass);

    MethodInfo method = type.GetMethod("ValidAdvert",
                                       BindingFlags.Instance | BindingFlags.NonPublic,
                                       null,
                                       new Type[] { item.GetType() },
                                       null);
    return (bool)method.Invoke(this, new object[] { item });
}

protected bool ValidAdvert(Derived1 item)
{
    return ADerived1SpecificPredicate;
}

protected bool ValidAdvert(Derived2 item)
{
    return ADerived2SpecificPredicate;
}

This pattern is called MultipleDispatch, while calling a method by reflection is slower than calling the method directly (it won't be an overhead if the method is called less than few hundred times per second), it has the benefit of not requiring to modify your class hierarchy like in the Double Dispatch pattern.

This will be even easier when c# 4.0 comes out with the dynamic keyword:

protected bool ValidAdvert(Base item)
{
    if (item.GetType() == typeof(Base))
        throw new ThisIsAnAbstractClassException();

    dynamic dynamicThis = this;

    return (bool)dynamicThis.ValidAdvert(item as dynamic);
}


A perfect place to use double dispatch:

class Base
{
    public abstract bool IsValid(IAdvertValidator validator);
}

class Derived1 : Base
{
    public bool IsValid(IAdvertValidator validator)
    {
        return validator.ValidAdvert(this);
    }
}

class Derived2 : Base
{
    public bool IsValid(IAdvertValidator validator)
    {
        return validator.ValidAdvert(this);
    }
}

interface IAdvertValidator
{
    bool ValidAdvert(Derived1 d1);
    bool ValidAdvert(Derived2 d2);
}


I'm not sure exactly how you will ever have an instance of the base class that isn't actually an instance of a derived class. Since the base class is abstract, it can't be instantiated. I suppose it would match any derived class that doesn't have a specific signature, but that doesn't seem to be what you're going for.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜