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!
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.
Related
I'd like to have some common logic shared between two screens, so I want to have an abstract class inheriting from PXGraph, and then two different Graphs inheriting from this abstract class.
Like this :
namespace LE
{
public abstract class ICarrySomeLogic : PXGraph<ICarrySomeLogic>
{
// common business logic
}
public class graph1 : ICarrySomeLogic
{
// specific business logic
}
public class graph2 : ICarrySomeLogic
{
// specific business logic
}
}
Does it work correctly ? Is there a "best practice" or another proper way to do it ?
Thanks a lot,
I have done this before and works great. Here is my example simplified...
public abstract class MyGraphBase<TGraph, TPrimary, TWhere> : PXGraph<TGraph, TPrimary>
where TGraph : PXGraph
where TPrimary : class, IBqlTable, new()
where TWhere : class, IBqlWhere, new()
{
public PXSelect<TPrimary, TWhere> document;
}
public class GraphOneEntry : MyGraphBase<GraphOneEntry, MyDac, Where<MyDac.docType, Equal<DocType.typeOne>>>
{
}
public class GraphTwoEntry : MyGraphBase<GraphTwoEntry, MyDac, Where<MyDac.docType, Equal<DocType.typeTwo>>>
{
}
My events in the base abstract class will fire and I can override as needed in the other graphs.
I have been using this since version 5.3
Edit: starting in 2017R2 there is a new concept around Reusable Business Logic that can also be utilized for this same purpose.
The example you have given should do what you need. The inheritable traits and behavior of your abstract class will be inherited by your subclasses as expected. This works for extension classes as well. If you extend an existing Graph, you can then subclass your extension class to achieve inheritance.
Note: The "I" prefix for type naming is a standard in C# for interfaces, not classes. Even though abstract classes have some similarities to interfaces, they are not the same. If you want to follow Microsoft best practices, you might consider not using this prefix for class naming. If your I prefix is simply meant as the word "I" (as in you, yourself), then you can just ignore this note. :)
It would be great if this would work. Am I trying to implement my idea in the wrong way?
I would like to use partial method, to be able to extend existing code, and simply plug in/out implementation of methods.
Basically exactly what the reference is stating:
Partial methods enable class designers to provide method hooks,
similar to event handlers, that developers may decide to implement or
not. If the developer does not supply an implementation, the compiler
removes the signature at compile time.
My first try of using this is the following:
DefinitionsBase.cs:
namespace ABC {
public partial class Definitions {
// No implementation
static partial void TestImplementaion();
}
}
DefinitionsExt.cs:
namespace ABC {
public partial class Definitions {
static partial void TestImplementaion(){
// Implementation is here
}
}
}
Program.cs:
namespace ABC {
class Program {
static void Main(string[] args) {
Definitions.TestImplementaion();
}
}
}
It's same namespace, but as reference states partial methods are implicitly private. It doesn't accept access modifiers and I cannot call it from my class. Is there a way to use it as I intend to?
Thanks!
You could use a public method that calls the private method, but I am not sure if this is what you want. This just makes your code work.
Partial methods are by definition private so as during compilation time, in case the method was not implemented, the compiler does not need to go through all of the code, find all possible references to the method, and remove them.
This is a design choice since partial methods do not necessarily need to be implemented, the compiler only looks in the partial class implementation and not throughout all of the code.
If you implement a public method that calls the partial method and the partial method was not implemented, the compiler will still only look in the partial class files and code, even though you have access to that partial method from anywhere in your code.
I have a DLL, that we bought and I can't access its source. However, for the problem that I'm now facing, I've been told that I must inherit from a class in the DLL, and override one of its methods.
I tried it and it works quite well, as expected. My problem now is that I have quite a few classes where I need to do the same thing, and don't want to repeat the same code so many times. Although all of those classes inherit from the same DLL class, it doesn't look good to me to write the same code in all of them.
This is the code for one class:
public class MyClass : DllClass
{
protected override void MethodFromDll()
{
//here I inserted my code and it works ok
}
}
Thanks
Why not create an abstract class which derives from DllClass and override the method there, then derive your other classes from that?
public abstract class MyClassBase : DllClass
{
protected override void MethodFromDll()
{
//here I inserted my code and it works ok
}
}
...
public class MyClass : MyClassBase
{
// Whatever else you need
}
That's assuming you need inheritance here in the first place - do you definitely need to have multiple derived classes, or could you have lots of classes which use MyClass by composition instead?
The tutorial application, MusicStore -MVC3 (92 PageNo), created a POCO class like:
public partial class ShoppingCart
{
MusicStoreEntities storeDB = new MusicStoreEntities();
public static ShoppingCart GetCart(HttpContextBase context)
{
var cart = new ShoppingCart();
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
}
How can we access static method in partial classes? In my opinion, we cannot access static methods in a partial class. The partial attribute means other parts of the class will be included in the namespace. In this scenario, I do not know where this other partial class is implemented.
My questions about this static method are:
Can we access static methods in partial classes? If so, how?
Where is this partial class implemented in this MusicStore application? I am not able to find the other part of this class's implementation.
Updated: There is no other ShoppingCart class in the models directory. Does anyone know where that partial implementation would be?
A partial class in C# can definitely access static methods. The partial attribute simply says a class can (not must) be defined accross multiple files and otherwise doesn't affect member lookup.
EDIT Responding to comment in question
A possible explanation for why you can't find the other implementation of ShoppingCart is it may not exist. A partial class is not required to have multiple definitions. The partial only means there may be other parts of the definition.
Yes, you can access static methods in partial classes.
Partial classes are just a way of representing a regular class in multiple source files, often with some of those source files controlled (or generated) by tools.
You can call ShoppingCart.GetCart(context) anywhere - it's a normal public static method.
It's still not really clear what your second question means, but there doesn't have to be another part at all. It's fine (though unusual) to have a partial class which is only declared in a single file.
I have a class formed by two partial classes.
One created by ORM code generation and one for extensions.
In this particular instance, I need to override one of the properties generated by the partial class because I need to do some validation on it first.
Is it possible to use my extension class to kind of override the property of the code generation partial class?
No, not possible. If you are the owner of the code-generation, you should put in hooks for handling that scenario. For example, sqlmetal.exe for LinqToSql produces partial classes wherein each property setter looks a bit like this:
if (this.myProperty != value)
{
this.OnMyPropertyChanging(value);
this.SendPropertyChanging();
this.myProperty = value;
this.SendPropertyChanged("MyProperty");
this.OnMyPropertyChanged();
}
Of course, the generator also creates those property-specific changing/change methods, but they declare those as partials:
partial void OnMyPropertyChanging(string newValue);
partial void OnMyPropertyChanged();
With this setup, it's obviously quite easy to tap into these events for the extension partial class.