I have a class like this
public class BaseClass
{
public string Request { get; set;}
}
and I have the class like this :
public class ExtendClass : BaseClass
{
}
So actually the property Request will always be set with the name of ExtendClass. So it actually will be Request="ExtendClass"
I have many class who extend BaseClass. I know I just can pass string to it, but is that possible to do it?
You can use object.GetType which will always return the type on top in the hierarchy (so the last deriving class):
public string Request
{
get
{
return this.GetType().Name;
}
}
Name will return the short type name, without the namespace. If you want that too, you should use FullName.
You have multiple choices. For example, you can use reflections:
public string Request { get {return this.GetType().Name; }}
Or you can make it more explicit, with abstract property (and that way you can specify not only class names):
public abstract class BaseClass
{
public abstract string Request { get; }
}
class ExtendClass : BaseClass
{
public override string Request { get {return "ExtendClass"; } }
}
Related
I'm having a hard time phrasing the question which is also making it hard for me to search for answers.
Here's a contrived scenario that mimics what I'd like to do:
void Main()
{
Console.WriteLine(TestClassA.MyPropertyName());
Console.WriteLine(TestClassB.MyPropertyName());
var speaker = new TestSpeaker();
speaker.Speak<TestClassA>();
speaker.Speak<TestClassB>();
}
public class TestSpeaker {
public void Speak<T>() where T : BaseClass<T> {
Console.WriteLine(/* I want to call T.MyPropertyName() here */);
}
}
public class TestClassA : BaseClass<TestClassA> {
public string Name { get; set; }
}
public class TestClassB : BaseClass<TestClassB> {
public string OtherPropertyName { get; set; }
}
public abstract class BaseClass<T> {
public static string MyPropertyName(){
return typeof(T).GetProperties().Single().Name;
}
}
The Console right now would read:
Name
OtherPropertyName
I'd like to replace my commented out code so that it would read:
Name
OtherPropertyName
Name
OtherPropertyName
if you change your Writeline to
Console.WriteLine(BaseClass<T>.MyPropertyName());
you will get what you want
Why use a static function in a base class to retrieve information about a derived class? In any case, you could implement a member function to wrap the static call:
public static string MyStaticFunction() => return "whatever";
public string MyMemberFunction() => MyStaticFunction();
But in your scenario, perhaps you should simply declare an abstract property (or function) meant to return the value you're looking for and override it in derived classes:
Base:
public abstract string MyPropertyName { get; }
Derived:
public override string MyPropertyName => nameof(OtherPropertyName); // or more complex logic
And yet another possible solution would be to pass the information to the base class's constructor as a string (or property expression should you be so inclined):
Base:
public string MyPropertyName { get; init; }
public BaseClass(string propertyName)
{
MyPropertyName = propertyName; // maybe validate that the property exists
}
Derived:
public MyTestClassB() : BaseClass(nameof(OtherPropertyName)) {}
I have an interface that a my class uses. I have a subclass that I need to reference this interface with. I can not seem to figure it out, here is the code:
Interface:
public interface ICanBeCalled
{
string NameCalled{ get; set; }
}
Parent class:
public class ParentClass: ICanBeCalled
{
private string _name;
public string NameCalled
{
get => _name;
set => _name = value;
}
// functions below are omitted as not part of question
}
Subclass:
public class SubClass : ParentClass
{
// Here I want to be able to set and get the name var,
// how can this be done?
// Ideally the set functionality would have it
// hard coded in a private string.
}
You can set the parent value in the constructor of SubClass
public class SubClass: ParentClass
{
SubClass()
{
this.NameCalled = "MyHardcodedName";
}
}
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; }
}
I have the following base class
public abstract class BaseRepository<T>
{
public abstract IEnumerable<T> GetAll();
}
And a class the inherits it.
public class CustomerRepository: BaseRepository<Customer>
{
public override IEnumerable<Customer>GetAll()
{
return null;
}
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
what i want to do is using this class
public class Sales
{
public int Id { get; set; }
public int CustomerId {get;set;}
public decimal Total {get;set;}
}
this doesn't work
public class SalesRepository: BaseRepository<Sales>
{
public override IEnumerable<Sales>GetAll(IEnumerable<Customer> Customers)
{
return null;
}
}
My question is, how to I modify my BaseClass to have optional ienumerable parameters of that i can then use as needed.
The GetAll(IEnumerable<Customer> Customers) function amounts to a new method. It does not have the same signature of the base, and so cannot be overridden in this way. The SalesRepository class, if it is to be a BaseRepository<Sales>, must implement the GetAll() method as is.
You can do this change
public class SalesRepository : BaseRepository<Sales>
{
public override IEnumerable<Sales> GetAll()
{
return GetAll(null);
}
public IEnumerable<Sales> GetAll(IEnumerable<Customer> Customers)
{
return null;
}
}
BaseRepository<Sales> rep = new SalesRepository();
rep.GetAll();
this will call overridden version and makes a call to GetAll(null).
To pass value to GetAll() method you need to have do the following
SalesRepository srep = new SalesRepository();
srep.GetAll(new Customer[] { new Customer() });
You can either mark parameter as optional or you can make overloads to the method in your base class, both of which will result in the same thing. When you mark a parameter as optional the compiler simply makes the overloads for you.
Ultimately you probably need to make two methods in your base class and then either hide one (make private) in your implementation of each parent class or have it throw an error. If you can figure out a good way to have default values then that may work as well.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new B("MyName").Name);
}
}
abstract class A
{
public A(string name)
{
this.GetType().GetField("Name").SetValue(this, name);
}
}
class B : A
{
public B(string name)
: base(name)
{
}
public string Name
{
set;
get;
}
}
}
Is it possible to do something like that?
I can't stress how very, very, very bad this is. You are creating an inverse coupling that is convoluted, confusing and contrived, severely lacking in clarity, failing best practices and object oriented principals, which is going to create a maintenance and management nightmare for people implementing derivatives of your abstract class. Do the right thing!!
abstract class A
{
protected A(string name)
{
Name = name;
}
public abstract string Name
{
get;
protected set;
}
}
class B: A
{
public B(string name) : base(name)
{
}
private string m_name;
public override string Name
{
get { return "B Name: " + m_name; }
protected set
{
m_name = value;
}
}
}
It is possible, but i wouldn´t recommend to do that. The problem is that your base class knows to much about the class that are derived from it.
When you derive a class from your abstract base class that does not define the property Name you get an Exception on runtime.
If you expect that each class, that is derived from your base class, has a property Name, then it would be easier to define the Property Name in your abstract base class and set the property with you constructor.
It's really bad form to do that. Generally you should just call a method like 'SetPossibleData()', and force all children to implement it in a fashion they decide.
Why do you need to do this?
Use GetProperty() Method,
public A(string name)
{
this.GetType().GetProperty("Name").SetValue(this,name,null);
}
It would be really straight forward if every class initializes the fields and properties it defines. Why does B expect the base class initialize its Name?
abstract class A
{
public A()
{
}
}
class B : A
{
// I know, its trivial, but it does the same ...
public B(string name) : base()
{
Name = name;
}
public string Name { set; get; }
}
The only thing I could think of why you wrote this code is that the base class has some logic to initialize the field. Straight forward would be to let the derived class call the logic, but initialize the field itself:
abstract class A
{
public A()
{
}
protected string GenerateName(string someArg)
{
// complicated logic to generate the name
}
}
class B : A
{
public B(string someArg) : base()
{
Name = base.GenerateName(someArg);
}
public string Name { set; get; }
}