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.
Related
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.
Background
I am using Linq to SQL and thus have a generated DBML file containing auto-generated classes. Part of the generation process creates partial methods for certain actions, and in my case the two methods I am interested in related to the Insert and Update of table records. These partial methods are generated per each Table created in the DBML designer, for example:
partial void InsertMyTable(MyTable instance);
partial void UpdateMyTable(MyTable instance);
Now part of the design of my application requires that these two partial methods are always implemented for every single table. (They are essentially used to add a timestamp to the record being inserted/updated).
Requirement
I have a unit test project, and although this may not be common practice I want to include a few tests that ensure certain things have been implemented properly. In this case I want to ensure that the developers have remembered to implement the partial methods mentioned above (I do NOT care about the actually implementation, only that they have been implemented).
Problem
What I need to do is use reflection to check if each partial method has been implemented, but I am having trouble working out how to determine that.
Attempted Efforts
So far I have managed to get a list of methods contained within the data context, and I am able to compare that with the methods expected for each table. The problem is that I can't find a way to determine if a given partial method actually has an implementation:
var methods = (typeof(MyDataContext)).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var method in methods)
{
Console.WriteLine(method.Name);
//how to check if method is implemented, or just an unimplemented partial
}
What you have already works. If the partial method doesn't have an implementation, then it does not exist at all. There is no "declaration stub" that you might find by reflection accidentally. Either the partial method has an implementation, or it is removed completely by the compiler.
So basically: if you can't find the method with GetMethod / GetMethods (with the appropriate BindingFlags, as per the question) - then it wasn't implemented.
As an alternative idea (and one that is obvious at compile-time, and which isn't susceptible to problems with obfuscation):
// generated code
public partial class Whatever : ISomeInterface<MyTable>
{
//...
}
//somewhere else
public interface ISomeInterface<T>
{
void Insert(T instance);
void Update(T instance);
}
Now the compiler won't let the user proceed without implementing this interface completely, presumably in a partial class:
partial class Whatever
{
public void Insert(MyTable instance) {...}
public void Update(MyTable instance) {...}
}
(note they can still use explicit interface implementation, but you should use that interface yourself when accessing the data; avoids even more reflection)
When I ran into the same problem I solved it as follows:
var Method = (typeof(Entities))
.GetMethods(System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance)
.FirstOrDefault(x => x.Name == "SomeMethodShouldBeOnPartialClass");
if (Method != null) Method.Invoke(this,null);
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 am working with Visual Studio Coded UI Tests, and wish to persist tweaks to the generated code.
The code is generated as a partial class in UIMap.cs and UIMap.Designer.cs, and so I know one solution would be to create a method with a slightly different name, such as myMethod_persist in UIMap.cs and use this instead of myMethod in UIMap.Designer.cs, which will be overwritten every time the source is regenerated.
This however seems very messy, and so what I'd prefer, is to instead override myMethod in UIMap.cs. This way the interface is not complicated with lots of gumph, and I don't have to remember to change every instance of myMethod in calling code to myMethod_persist
Unfortunately when it comes to C# I'm a bit of a noob, and don't even know if this is possible.
Basically what I want is this:
[UIMap.Designer.cs]
partial class myClass
{
public override void myMethod( int a ){ somethingHorrible(int a); };
}
[UIMap.cs]
partial class myClass
{
public sealed override void myMethod( int a ){ somethingNice(int a); };
}
But I know that the sealed and override keywords are usually used with derived subclasses classes, not partial classes. Is this possible? If not then what would be my best alternatives?
There's only one class here - myClass. The partial keyword just allows the class definition to be split across multiple files.
You can use partial methods, but only if the original (generated) method uses the partial keyword. You cannot override a method on the same class.
See Partial Classes and Methods (C# Programming Guide).
If you have no control over the auto-generation itself (ie. a framework or 3rd party generator) your options are somewhat limited. The two approaches that come to mind are to modify the generated code--which as you noted is not practical for changes that are significant and perhaps accumulating over time--and/or to create a derived class and use that instead of using the auto-generated class directly (assuming you control the code which would be using them, which seems likely).
A derived class (inheriting the auto-generated class) would be able to use override or new in the method declarations you want to replace. However, there are a lot of caveats to this approach as well. You can only "override" a method that was delcared as virtual in the base class (or was itself an override of another underlying virtual base, etc). You can also replace a method with a "new" one in the derived class, but the other code in the base class will not know about your "new" version and will not call it (whereas they will call your "override" because they know the method to be virtual). There are also issues of accessiblity; your derived class won't have access to private members of the base class.
But for some set of things you want to do it could work. In some cases you might have to tweak the auto-generated code slightly such as adding the keyword "virtual" or changing "private" members to "protected" so that you can access them from your derived class.
Added: Of course, you can also add new members to the original generated class in your own permanent file for the same partial class, and this code would have access to the class's private members. That can be another way to give your derived class access to the private members, such as by creating a protected property to wrap access to a private member field. If you didn't need to make changes to existing methods you wouldn't necessarily need to create a derived class, but your example talked about wanting to "override" methods from the auto-generated code, so presumably they already exist there.
Also note that a Designer file--such as for a Form or UserControl--does not usally get completely overwritten, so cautious changes outside the core generated code (eg. not inside the "Windows Form Designer generated code" region) can be made (and are persisted). For example, it is sometimes necessary to add a call to your own custom clean-up method in the Dispose(...) method in the Designer file.
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.