I wanna see if there is anyway that when the child property method is being called, it will call the parent property as well.
Note that the child is generated by a code generator from edmx. So I can't change anything except adding a partial class for the child class. (It might be too trouble to change the generator.)
The situation I am having :
I have a class "MyClass" that is automatically generated from the database. I can't change anything on it except adding a partial class or change the code generator.
Now, I need to "do something" whenever the property Name is being called. I am thinking if I can put a parent there and make it call the parent to do "something" when the child property is "Name" is being called.
What I want :
public class ClassBase
{
public string Name
{
get
{
CallMethod();
return Name;
}
}
}
public class MyClass : ClassBase
{
public string Name { get; set; }
}
MyClass myClass = new MyClass();
myClass.Name; < -- this will call the parent as well.
Is there anyway to do it?
Thanks in advance
Not really related but since you're not strictly using automatic properties in ClassBase, you should create a private string variable for Name. Something like _name or whatever your internal coding standards dictate.
public class ClassBase
{
private string _name;
public virtual string Name
{
get
{
CallMethod();
return _name;
}
set
{
_name = value;
}
}
}
public class MyClass : ClassBase
{
//Pretty pointless really since you're not doing anything with MyClass.Name.
public new string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
MyClass myClass = new MyClass();
myClass.Name; <-- this will call the parent as well.
Based on "can't change base class" comment there is pretty much nothing you can do to make some code to be executed instead/before/after base class because your property/method will not be called when your new class used as base class (see sample in details part).
Potential solution : if you need to extend specially designed parital class's and it provides extension poinst like CallMethod is marked as partial - it is expected for implemnting portion of the class to implement it :
partial public class ClassBase
{
partial void CallMethod();
public string Name {get {CallMethod(); return "";}}
}
// in generated portion of "ClassBase"
partial public class ClassBase
{
partial void CallMethod() { /* do something here */ }
}
Answer to exact "how to call base class property" is to use base, but hiding property/method this way is confusing (see below):
new public string Name { get { return base.Name;} }
Note that you can't use automatic property in derived class case as you explicitly want some additional code to be executed. If you need set in derived class you need own backing field like:
private string derivedName;
new public string Name {
get { return base.Name + derivedName;}
set { derivedName = value;}
}
Details:
As said in comments hiding base class' properties/methods leads to very confusing behavior. For you case (slightly updated base class with baking field as original sample had infinite recursion):
public class ClassBase
{
private string name;
public string Name
{
get
{
CallMethod();
return name;
}
}
}
You can try to hide Name property in derived class:
public class MyClass : ClassBase
{
// notice "new" to show comiler you know what you doing
// otherwise you'll get warning (but behavior will be the same)
new public string Name { get; set; }
}
The issue with hiding is that base class' method is still easily callable and likely be called by mistake if using derived class as base class:
MyClass myDerved = new MyClass();
ClassBase myDervedAsBase = myDerved;
var name = myDerived.Name; // calls MyClass.Name
var name = myDerivedAsBase.Name; // calls ClassBase.Name
This can be solved by making base class' method/property virtual - but it requires change in base class:
public class ClassBase
{
virtual public string Name { get {... } }
}
public class MyClass : ClassBase
{
override public string Name { get { ... } }
}
If you need to call base class' method/property from derived class usebase.MethodName() like:
override public string Name { get
{
// do some new stuff here
var baseName = base.Name;
// maybe even change result
return baseName;
}
}
If you expect most derived classes to need such behavior it could be better to design base class explicitly to enforce such behavior. For example you can have property to call virtual method before/after computing the value to return like:
public class ClassBase
{
virtual protected string AboutToReturnName(string result)
{
return name;
}
public string Name
{
get
{
var result = "MyName";
return AboutToReturnName(result);
}
}
}
More ideas:
Alternative to virtual is partial methods which works when instead of deriving class is combined from many "partial" parts like ASP.Net pages - see Partial Classes and Methods
If you need notifications around change of property - consider implementing INotifyPropertyChange
if you need to know when properties/method are called in general - consider using interfaces and automatically generate wrapper classes that have pre/post callback. I.e. mocking frameworks (like EasyMoq or RhinoMock) and DI containers (like Unity) provide and use such functionality.
You cannot do it without modifying the code generator. The modification would have to generate a call base.Name.
You can override the property in your subclass with the new operator.
public class MyClass : ClassBase
{
public new string Name { get; set; }
}
Related
Is there a better way of doing the following ...
I have a base class which provides a default implementation of the DisplayName property. Obviously optionally set, not required.
Edit: I can't use an interface instead of this base class, because I have behavior in it, which is trimmed out in this example.
public abstract class BaseObject
{
public virtual string DisplayName { get; protected set; }
public BaseObject(string displayName)
{
if (!string.IsNullOrWhiteSpace(displayName))
{
this.DisplayName = displayName.Trim();
}
}
// There is common behavior, unrelated to DisplayName here ... trimmed out of this sample code.
}
I have a system object class, derived from BaseObject, but providing its own implementation of DisplayName
public class SystemObject : BaseObject
{
public override string DisplayName
{
get
{
return string.Format("TODO: Resources.{0}", this.Id);
}
// EDIT: Turns out I can't even do that, because EF can't materialize the property. So, it needs to be an empty protected setter.
protected set { throw new InvalidOperationException("Do not set this property!"); }
}
public SystemObject() : base(null)
{
}
}
and I have a user-defined object, derived from the same base class:
public class UserObject : BaseObject
{
public UserObject(string displayName) : base(displayName)
{
if (string.IsNullOrWhiteSpace(displayName))
{
throw new ArgumentNullException("displayName");
}
}
public void ChangeDisplayName(string newDisplayName)
{
if (string.IsNullOrWhiteSpace(newDisplayName))
{
throw new ArgumentNullException("newDisplayName");
}
this.DisplayName = newDisplayName.Trim();
}
}
which utilizes the DisplayName from BaseObject to store a user-provided display name.
I can't make the DisplayName in BasObject abstract, because I am doing EF code first.
I am particularly concerned about protected set { throw new InvalidOperationException("Do not set this property!"); }. Any way to avoid this?
Don't use an abstract class at all when you don't actually want to define any behavior. If you just want a way of saying that there are different objects with a DisplayName property getter, then create an interface that defines such a contract that these two classes can implement in their own ways.
I think I see where you are going with this.
Leave the property alone. Just make it a get-only property in the base class, but make the getter call an abstract method:
public string DisplayName { get { return GetDisplayName(); } }
Then declare the method as abstract:
protected abstract string GetDisplayName();
That will force your inheriting classes to provide an implementation of how to return a display name. You can then change your UserObject class to store the name internally during instantiation and return it in the implementation of the method.
You could simply stub it out to do nothing;
public string DisplayName { set {} ...}
I have the following code (ready to paste into linqpad). Basically there is a base 'model' class with a 'treemembermodel' class deriving from it.
class MemberModel
{
public List<Member> Team = new List<Member>();
public void IncreaseAge()
{
// Would like this to modify the Treemember
Team[0].Age++;
}
}
class TreeMemberModel : MemberModel
{
public new List<TreeMember> Team = new List<TreeMember>();
public void UpdateName(string newName)
{
}
}
Same for a Member class with a 'TreeMember' deriving from it.
public class Member
{
public string Name;
public int Age;
}
public class TreeMember: Member
{
public string ParentName;
}
The idea is that the base member model stores a list of normal members, while the 'tree' model (and member) classes ensure a 'tree' structure by maintaining integrity between parent and subordinate fields.
This all seemed a good idea (the below example is stylised) - I figured any 'common' methods applying to both object types (eg 'increaseage' below) would modify the treeMember in the TreeModel when called from that model. However, calling 'increaseage' in my main method instead tries to access the 'Team' collection from the base 'MemberModel' instead, which of course doesn't exist.
void Main()
{
TreeMemberModel t = new TreeMemberModel();
t.Team.Add(new TreeMember() { Name = "original", Age = 10 });
// Call method within derived class
t.UpdateName("changed");
Console.WriteLine (t.Team[0].Name);
// Call method which drops down to base class method, and would like it to modify the TreeMemberModel's Team collection, not MemberModel's.
t.IncreaseAge();
Console.WriteLine (t.Team[0].Age);
}
I figure this is a covariance issue, and have tried a few things around making classes generic and so forth. Can I configure this so it drops back to the base class's methods while manipulating the elements of the TreeModel collection?
You should try following:
class MemberModel<TMember> where TMember : Member
{
public List<TMember> Team = new List<TMember>();
public void IncreaseAge()
{
// Would like this to modify the Treemember
Team[0].Age++;
}
}
class TreeMemberModel : MemberModel<TreeMember>
{
public void UpdateName(string newName)
{
}
}
I read other threads like this but they didn't work for me.
I got two classes:
public class ClassA
{
public string _shouldBeInteger;
public string _shouldBeBool;
public string _shouldBeDateTime;
}
public class ClassB : ClassA
{
public int? shouldBeInteger
{
get { return (_shouldBeInteger != null) ? Convert.ToInt32(Convert.ToDouble(_shouldBeInteger)) : new int?(); }
set { _shouldBeInteger = Convert.ToString(value); }
}
//... same thing with datetime etc.
}
If I now create a new object of ClassB I get
_shouldBeInteger, _shouldBeBool, _shouldBeDateTime;
shouldBeInteger,shouldBeBool,shouldBeDateTime
But I want to hide the _variables to the User.
Setting them private in ClassB will override them, but I need to access them in order to parse there string values.
Update
There is a ClassC filling ClassAs' values, which mainly is the reason why they have to be writeable. There is no way for me to change the way that works, but I'm fully in Control of ClassA and ClassB
ClassC //not changeAble for me
{
//infomagic filling values of ClassA
}
Setting ClassA variables to private won't work, because programmer of ClassA produced it in a strange way.
Solution
Because ClassA needs to be writeable, but not readable to other classes than inheritated, I finally got this:
ClassA
{
public string _shouldBeInteger { protected get; set; }
//and so on
}
which causes ClassB to work with theese properties, without giving them outside.
Intellisense still shows them, but you might consider using:
[EditorBrowsable(EditorBrowsableState.Never)]
to solve that.
Thanks to all.
I think you can solve your problem using:
public class ClassA
{
protected string _shouldBeInteger;
protected string _shouldBeBool;
protected string _shouldBeDateTime;
}
so those variables are accessible to derived classes but not to user.
EDITED after user update:
I don't know if this could be a vali solution for you, but try:
public class ClassB : ClassA
{
public new int? _shouldBeInteger
{
get { return (base._shouldBeInteger != null) ?
Convert.ToInt32(Convert.ToDouble(base._shouldBeInteger)) :
new int?(); }
set { base._shouldBeInteger = Convert.ToString(value); }
}
}
Inheritance can't hide the members as you would think. The new modifier exists to "hide" a base member, but that doesn't play nice when talking to base types.
http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
You can either change the access level of the fields (the preferred way) or you can wrap the class instead of inheriting from it and provide simple pass-through methods to delegate to the wrapped class. This is called the Adapter Pattern:
public class ClassB
{
private ClassA _wrappedClass;
}
Just as an aside, your public fields are following the naming convention commonly used for private fields.
The required access level for derived classes is protected. If the members are used publicly but in the same assembly you can use protected internal. If the members are used publicly by other assemblies... I'd suggest refactoring.
The problem is that you declared the fields public in the base class. In order not to violate the polymorphic nature of inheritance, anything public in the base class must be public in all derived classes as well. If you could change that, you could never be sure that a ClassB could be passed to something expecting a ClassA.
Therefore, as other people have suggested, you probably want the base class fields to be declared protected, which is like private except derived classes can see them.
However if you do need to access them via an actual instance of ClassA, you could declare them private and give them virtual public properties which the derived class can then override. This at least allows the derived class to change their behaviour, but it still can't actually hide them.
If that also doesn't fit, then it's probably worth considering using composition instead of inheritance because the substitution principle is actually getting in your way, and that's an inheritance fundamental.
If you don't have control over ClassA, you'll need to create a wrapper/adapter class like so:
public class ClassB
{
private readonly _classA = new ClassA();
public int? shouldBeInteger
{
get
{
return (this._classA._shouldBeInteger != null)
? Convert.ToInt32(Convert.ToDouble(this._classA._shouldBeInteger))
: new int?();
}
set
{
this._classA._shouldBeInteger = Convert.ToString(value);
}
}
}
public class ClassB
{
private int shouldBeInteger;
public int ShouldBeInteger
{
get { return shouldBeInteger; }
set { shouldBeInteger = value; }
}
}
OR
public class ClassB
{
public int ShouldBeInteger{ get; set; }
}
In both of this case ShouldBeInteger will be accesible outside the class.
In first case there were a private field, which cannot be accesible outside the class,
values to private filed can be set through the public field.
In second case the compiler automatically create a private backing field and do the same
process as above. This is auto implemented property.
Hope this may help you.
I have a class like the below, I want to override the set value of "School,Country..etc.." property when some one sets a value , i don't want to change the student class but i need to do it in the base class and use it as a generic method
public class Student : BaseClass
{
public String School { get; set; }
public String Country{ get; set; }
}
ie:
When some one sets
Student.School="Harvard",
I need to store it as
Student.School="Harvard my custom value";
Note:
Basically calling OnPropertyChanged in base class rather than the main class.
If you want to do it with aspects, then try Postsharp
Basically you cannot override a non-virtual property. You can hide it by other property with the same name in the derived class, but this won't give you the desired effect if some other code accesses your object by the reference to the base class.
public class Student : BaseClass
{
private string _school
public string School
{
get { return _school; }
set
{
if(value == "Harvard")
value = "Harvard custom";
_school = value;
}
}
public String Country{ get; set; }
}
is that what you mean?
If the School property is in the BaseClass then you can either use the new keyword, or if you control the BaseClass, then you can add the virtual keyword to the School property there, and override it in the Student class.
This is just not doable by solely modifying BaseClass. Think about it this way: If it were possible to "annotate" automatic properties that easily, then we wouldn't need all those <rant>useless tons of</rant> manual property implementations for data model classes that implement INotifyPropertyChanged (same for DependencyProperties).
You need to provide hooks in your subclasses that your base class can use. Implementing PropertyChanged, which you already mentioned, is one possible solution, another one would be a simple method call:
public class Student : BaseClass
{
private string _school;
public String School
{
get { return _school; }
set {
_school = value;
DoMoreChanges(ref _school); // DoMoreChanges is defined in BaseClass
}
}
public String Country{ get; set; }
}
If you have lots of subclasses that need this, you can either use Visual Studio Code Snippets to create the code or T4 templates.
Since your base class does not have those properties you will not be able to modify them from within the base class using standard OOD patterns or principles.
Now if you move the properties to your base class either as normal properties or virtual properties you can modify what you do in the set block of the properties to do extra work.
However if you cannot move these to the base class, and you cannot modify the Student class, as you seem to imply in you question, then you could encapsulate the student class within a new class like StudentProxy or something and then have it expose similar properties that will then call into the real student class how you want.
For example:
public class StudentProxy
{
private Student _student;
public StudentProxy(Student student)
{
this._student = student;
}
public String School
{
get { return _student.School; }
set
{
_student.School = value + " my custom value";
}
}
public String Country
{
get { return _student.Country; }
set
{
_student.Country = value + " my custom value";
}
}
}
I want to know if its possible to hide a base class property from a derived class:
Example:
class BaseDocument
{
public string DocPath{get; set;}
public string DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
//this class should not get the DocContent property
public Test()
{
DerivedDocument d = new DerivedDocument();
d.//intellisense should only show me DocPath
//I do not want this class to see the DocContent property
}
}
I cannot make the DocContent property private, because I want to instantiate the BaseDocument class elsewhere and use the property there. That will kill the idea of a property anyway.
One way to fix this would be to use a interface, say IDoc, which exposes DocPath property and make both the BaseDocument and DerivedDocument implement the interface. This will break their parent-child relationship though.
I can play with the new and override keywords, but that's not the right way either because the child still 'sees' the property
I tried using the 'sealed' keyword on the DocContent, but that does not seem to solve the problem either.
I understand that it 'breaks' inheritance, but I guess this scenario should be coming up frequently where a child needs to get everything else from the parent but one or two properties.
How can such scenarios be handled gracefully?
I'm not sure inheritance would be the way to go here. Yes, you can hack around it by using the EditorBrowsableAttribute but I think the design should be rethought. One possible approach:
public interface IDoc
{
DocPath{get;set;}
}
class BaseDocument : IDoc
{
public DocPath{get; set;}
public DocContent{get; set;}
}
class DerviedDocument
{
public DerivedDocument(IDoc doc)
{
this.Doc = doc;
}
public IDoc Doc{get;set;}
public Test()
{
DerivedDocument d = new DerivedDocument(new BaseDocument());
d.//here you will only see d.IDoc which only exposes DocPath
}
}
Basically, use composition instead of inheritance, and program to an interface, not to an implementation.
You can do it easily if you don't mind having BaseDocument and DerivedDocument in different assemblies/projects.
Make DocContent internal. It'll be visible to everything in the same project as BaseDocument, but it won't be visible to DerivedDocument since that's in a different project. Of course, you'll need to make BaseDocument public (right now you have it as the default, internal).
In first project:
public class BaseDocument
{
public string DocPath {get; set;}
internal string DocContent {get; set;}
}
In second project that references first:
class DerivedDocument : FirstProject.BaseDocument
{
public Test()
{
DerivedDocument d = new DerivedDocument();
d. //intellisense shows DocPath, but not DocContent
}
}
This solution has the advantage of not being a kludge. You can still use BaseDocument's DocContent property within BaseDocument's project. If you need to use DocContent in another project (separate from the project DerivedDocument is in), you can use the InternalsVisibleTo attribute to make DocContent visible to that assembly. (That, however, is in my opinion a kludge, albeit a very handy one in some scenarios.)
It sounds like you want to intentionally violate the Liskov Substitution Principle. Why bother with subclassing at all if it's not going to have the conventional inheritance semantics? Just make a separate class.
interface IBaseDocument
{
string DocPath { get ; set ; }
string DocContent { get ; set ; }
}
class BaseDocument : IBaseDocument
{
public string DocPath { get ; set ; } // implement normally
private string MyDocContent ; // use this in BaseDocument
string IBaseDocument.DocContent // implement explicitly
{
get { return MyDocContent ; }
set { MyDocContent = value ; }
}
}
class DerviedDocument : BaseDocument
{
public void Test ()
{
// error: The name 'DocContent' does not exist in the current context
Console.WriteLine (DocContent) ;
}
}
A late reaction, but there are several ways to do this.
Most beautiful: Place your Base class in a separate assembly and mark the property DocContent as internal instead of public:
class BaseDocument
{
public string DocPath{get; set;}
internal string DocContent{get; set;} //won't be visible outside the assembly
}
Or use attributes to hide the property from the source editor:
class BaseDocument
{
public string DocPath{get; set;}
public string DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
//this class should not get the DocContent property
[Browsable(false), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public new string DocContent{ get; set; }
public Test()
{
DerivedDocument d = new DerivedDocument();
d.//intellisense will only show me DocPath
//I do not want this class to see the DocContent property
}
}
I don't believe there is a good (or any) way to do this. You may have to break the hierarchy, or you could remove the DocContent property from BaseDocument, then derive two sepearate classes from BaseDocument, one which is your current DerivedDocument, and another which has the DocContent property.
Just do this.
class BaseDocument
{
public DocPath{get; set;}
public virtual DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
public override DocContent
{
get { return null; }
set { }
}
}
Or
public override DocContent
{
get { throw new NotImplementedException("Do not use this property!"); }
set { throw new NotImplementedException("Do not use this property!"); }
}