views:

127

answers:

1

I am following the Nerd Dinner tutorial as I'm learning ASP.NET MVC, and I am currently on Step 3: Building the Model. One part of this section discusses how to integrate validation and business rule logic with the model classes. All this makes perfect sense. However, in the case of this source code, the author only validates one class: Dinner.

What I am wondering is, say I have multiple classes that need validation (Dinner, Guest, etc). It doesn't seem smart to me to repeatedly write these two methods in the partial class:

public bool IsValid
{
    get { return (GetRuleViolations().Count() == 0); }
}

partial void OnValidate(ChangeAction action)
{
    if (!IsValid)
    {
        throw new ApplicationException("Rule violations prevent saving.");
    }
}

What I'm wondering is, can you create an abstract class (because "GetRuleViolations" needs to be implemented separately) and extend a partial class? I'm thinking something like this (based on his example):

public partial class Dinner : Validation {
    public IEnumerable<RuleViolation> GetRuleViolations() {
        yield break;
    }
}

This doesn't "feel" right, but I wanted to check with SO to get opinions of individuals smarter than me on this. I also tested it out, and it seems that the partial keyword on the OnValidate method is causing problems (understandably so). This doesn't seem possible to fix (but I could very well be wrong).

Thanks!

+2  A: 

I'm wondering is, can you create an abstract class ... and extend a partial class?

Sure, the partial keyword simply indicates that the class is implemented in multiple files - it has no real bearing on inheritance ... except in one narrow respect:

If the partial class contains a reference to a forward-declared partial method, but no part of that class implements that partial method - all calls to that partial method will be omitted by the compiler.

So what does this mean. If your partial class declares a partial method in one of it's parts, but no other part of your class defines the partial method - then you can't call that partial method in any derived classes ... since it won't exist.

Let's look at an example:

// file1.cs  (code gen'd)
public partial class Validation {
    partial void OnValidate(ChangeAction action);

    private void SomeMethod() {
        OnValidate( ChangeAction.Whatever );
    }
}

// file2.cs (Validation class body)
public partial class Validation {
    //partial void OnValidate(ChangeAction action) { ... }
}

public class Dinner : Validation {
    public void SomeOtherMethod() {
       OnValidate(null); // won't compile ... OnValidate doesn't exist
    }
}

You should also be aware that partial methods cannot have modifiers (like new, abstract, virtual, public, private, etc). This means you cannot override a partial method in a derived class. You can, however, define a virtual method that a partial method calls.

To your general question, there's nothing wrong with inheriting from partial classes or trying to avoid duplication of code. However, you need to work within the one or two limitations that partial classes/methods impose.

In your example, if you want to avoid duplicating logic, you may need to define your partial methods in the base class to make sure they are always available. Derived classes would not be be able to override them - but if this is needed, then just don't make those methods partial.

LBushkin
@LBushkin - Thank you for such a well written answer. Coming from a Java world, I'm not yet used to some of these concepts, so I appreciate the clarification and the additional information. Thanks!
JasCav