I trying to figure out how to write a class where the base class would supply the accessor functions and then the instanced class only needs to supply the values.
Something like this:
public interface IBaseClass
{
int GetHandlerID();
}
public abstract class AbstractClass : IBaseClass
{
private int HandlerID;
public virtual int GetHandlerID()
{
return (this.HandlerID);
}
}
public class MyClass : AbstractClass
{
int HandlerID = 1;
}
class Program
{
static void Main(string[] args)
{
MyClass newClass = new MyClass();
Console.WriteLine("HandlerID: {0}"), newClass.GetHandlerID() );
}
}
It doesn't work this way because the class is going to read the HandlerID in the AbstractClass instead of the MyClass variable. Using Virtual or Abstract isn't valid for variables, so I'm not sure how to do this other than having to implement properties every time a new class is derived.
What I'm trying to do is supply an interface for people to build their own plug-in class and it would use the accessor methods that are supplied with the base class. I don't want to have to implement the same property method every time I create a new instance of the class.
I figured out a way to do what I wanted. This way I can have default getters/setters in the base class and not have to create those in each definition that uses the base. It's not quite what I was looking for, but it'll work.
public abstract class AbstractClass : IBaseClass
{
private int m_HandlerID = 0;
public int HandlerID
{
get { return (this.m_HandlerID); }
set { this.m_HandlerID = value; }
}
private string m_HandlerDescription = "undefined";
public string HandlerDescription
{
get { return this.m_HandlerDescription; }
set { this.m_HandlerDescription = value; }
}
}
public class MyClass: AbstractClass
{
public MyClass()
{
HandlerID = 1;
HandlerDescription = "MyClass";
}
}
class Program
{
static void Main(string[] args)
{
MyClass newClass = new MyClass();
Console.WriteLine("Handler: {0}[{1}]", newClass.HandlerDescription, newClass.HandlerID);
}
}
public abstract class AbstractClass : IBaseClass
{
public AbstractClass(int handlerId)
{
this.HandlerId = handlerId;
}
public int GetHandlerID()
{
return (this.HandlerID);
}
}
public class MyClass : AbstractClass
{
public MyClass():base(1)//specific handler id
}
How about passing the value through the base constructor
The derived class needs able to access the HandlerID to ovewrite it, so you'll need to change it in the abstract class from 'private' to 'protected'.
public interface IBaseClass
{
int GetHandlerID();
}
public abstract class AbstractClass : IBaseClass
{
protected virtual int HandlerID { get; set; }
public virtual int GetHandlerID()
{
return (HandlerID);
}
}
public class MyClass : AbstractClass
{
private int _handlerID = 1;
protected override int HandlerID { get { return _handlerID; } set { _handlerID = value; } }
}
private static void Main(string[] args)
{
var newClass = new MyClass();
Console.WriteLine("HandlerID: {0}", newClass.GetHandlerID());
Console.ReadKey();
}
Related
How can I get the name of a class through a reference to an instance of a subclass?
For example,
public class BaseClass
{
public void ClassName()
{
// How can I get the name of the base class "BaseClass" here, without having to hardcode "BaseClass"?
Console.WriteLine(this.GetType().Name);
}
}
public class SubClass: BaseClass
{
public void ClassName()
{
base.ClassName();
Console.WriteLine(this.GetType().Name);
}
}
public static void Main(string[] args)
{
SubClass MyObject = new SubClass();
MyObject.ClassName();
}
The output is
SubClass
SubClass
But I want
BaseClass
SubClass
Thanks.
Generic Method
Probably the cleanest approach:
public static class TypeHelperExtensions
{
public static string GetTypeName<T>(this T Object)
{
return typeof(T).Name;
}
}
And then:
public class BaseClass
{
public virtual void ClassName()
{
// How can I get the name of the base class "BaseClass" here, without having to hardcode "BaseClass"?
Console.WriteLine(this.GetTypeName());
}
}
public class SubClass: BaseClass
{
public override void ClassName()
{
base.ClassName();
Console.WriteLine(this.GetTypeName());
}
}
nameof()
public class BaseClass
{
public virtual void ClassName()
{
// How can I get the name of the base class "BaseClass" here, without having to hardcode "BaseClass"?
Console.WriteLine(nameof(BaseClass));
}
}
public class SubClass: BaseClass
{
public override void ClassName()
{
base.ClassName();
Console.WriteLine(nameof(SubClass));
}
}
Reflection
public class BaseClass
{
public virtual void ClassName()
{
// If you know you will have only one parent
var b = type.BaseType.Name
}
}
if you don't know the structure you may have to do something like the following:
private bool _ignoreMe;
public void ClassName()
{
var b = this.GetType().GetField(nameof(_ignoreMe), BindingFlags.NonPublic | BindingFlags.Instance).DeclaringType;
}
I am calling the base constructor but somehow I need to point to the child one back. Take a look at the example bellow:
//Child
public CompanyEventsView(IAggregator aggregator, IRepository<CompanyEvents> repository, int i)
: base(aggregator, repository, i)
{
}
//Base
public BaseViewModelFor(IAggregator aggregator, IRepository<TSource> repository, int i)
{
Aggregator = aggregator;
var source = repository.GetKey(i);
this.MapFromSourceObject(source); // So "This" here should be pointing to the child class
}
Is there any way of doing this?
this and base do not refer to different instances, they are the same.
If your MapFromSourceObject method is defined in the child class, you can cast this to the child type like: (this as CompanyEventsView).MapFromSourceObject(source).
But this would defeat the whole point of inheritance.
Maybe define MapFromSourceObject as abstract or virtual in the base class?
If your base class depends the implementations of child classes, making the class itself abstract would be a better idea.
Maybe this example helps you a little bit with inheritance:
namespace CSharpConsoleApplication.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
class TemporaryTest
{
public static void Run()
{
Mother<FirstCompanyEvent> firstChild = new FirstChild(new FirstCompanyEvent("this is wrong"));
firstChild.Print();
Mother<SecondCompanyEvent> intChild = new SecondChild(new SecondCompanyEvent("you are too young to do this"));
intChild.Print();
}
}
public abstract class BaseCompanyEvent
{
protected string Value { get; private set; }
public BaseCompanyEvent(string value)
{
Value = value;
}
public abstract string GetMessage();
}
public class FirstCompanyEvent : BaseCompanyEvent
{
public FirstCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "First born: " + Value;
}
}
public class SecondCompanyEvent : BaseCompanyEvent
{
public SecondCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "Younger brother: " + Value;
}
}
public abstract class Mother<T> where T : BaseCompanyEvent
{
protected T CustomEvent { get; private set; }
public Mother(T customEvent)
{
CustomEvent = customEvent;
}
public abstract void Print();
}
public class FirstChild : Mother<FirstCompanyEvent>
{
public FirstChild(FirstCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
public class SecondChild : Mother<SecondCompanyEvent>
{
public SecondChild(SecondCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
}
I need to create a dll file which contains all the interfaces of the classes but doesn't contain any class.
Because I use these interfaces for a lot of classes it's must be like that:
public interface IClassA
{
string Word { get; }
}
public interface ITest<TClassA> where TClassA : IClassA
{
TClassA A { get; }
}
Example of two classes that implements these interfaces the way I want:
public class ClassA : IClassA
{
public string Word
{
get;
private set;
}
public string Sentence
{
get;
private set;
}
public ClassA(string word, string sentence)
{
this.Word = word;
this.Sentence = sentence;
}
}
public class Test : ITest<ClassA>
{
public ClassA A
{
get;
private set;
}
public Test(ClassA a)
{
this.A = a;
}
}
And I want to do something like that in the main program:
public static void Main(string[] args)
{
ClassA a = new ClassA("hey", "hey world!");
Test t = new Test(a);
Print((ITest<IClassA>)t);
}
public static void Print(ITest<IClassA> t)
{
Console.WriteLine(t.A.Word);
}
But this casting: (ITest<IClassA>)t makes a run time error.
How can I solve it?
thanks!
You should declare Test as
public class Test : ITest<IClassA>
instead of ITest<ClassA>.
Or declare ITest<TClassA> to be covariant on TClassA:
public interface ITest<out TClassA> where TClassA : IClassA
The Test-class implements the concrete ClassA (public class Test : ITest<ClassA>).
So you're trying to cast an ITest<ClassA> to ITest<IClassA> which obviously fails.
If you let the Test-class implement IClassA, the cast works:
public class Test : ITest<IClassA>
{
public IClassA A
{
get; private set;
}
public Test(IClassA a)
{
this.A = a;
}
}
I'm trying to create instance of class Bar but I'm receiving an error:
"Cannot implicitly convert type ConsoleApplication1.Bar to
ConsoleApplication1.BaseFoo<ConsoleApplication1.baseOutput,
ConsoleApplication1.baseInput>"
Any idea what I'm missing or what I'm doing wrong? Any advice will be nice.
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public class BaseFoo<baseOutput, baseInput>
{
protected virtual void DoSmth()
{
}
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
protected override void DoSmth()
{
base.DoSmth();
}
}
public class Test
{
public void Show()
{
}
private BaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar(); // Error right here
}
}
I'll give you an example of why you're prevented from doing that.
Imagine instead, your classes were written like this:
public class BaseFoo<TOutput, TInput>
where TOutput : BaseOutput
{
public TOutput Something { get; set; }
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
}
public class BaseInput { }
public class BaseOutput { }
public class ExtendOutput : BaseOutput { }
public class SomethingElse : BaseOutput { }
Now, you have this method:
private BaseFoo<BaseOutput, BaseInput> CreateInstance()
{
//At this point, Something will be of type ExtendOutput.
return new Bar();
}
So, we call it like this:
var myBar = CreateInstance();
Now, mybar.Something is of type BaseOutput. That's fine, though, because ExtendOutput : BaseOutput, right? Not quite.
What happens when we do this:
myBar.Something = new SomethingElse();
That's valid, because Something expects a BaseOutput, and SomethingElse is a BaseOutput. However, the object is actually a Bar, which explicitly says it should be an ExtendOutput.
The problem is clearer if we attempt to cast it back:
var myBaseFoo = CreateInstance();
myBaseFoo.Something = new SomethingElse();
Bar myBar = (Bar)myBaseFoo;
myBar.Something; // Here, we're told it's going to be an `ExtendOutput`,
// but we get a `SomethingElse`?
That's clearly wrong. And that's why you're prevented from doing what you're trying to do. You can have this behavior with covariance.
Covariance makes it illegal to pass in a TOutput. So, this line
public TOutput Something { get; set; }
Would be invalid. We would only be allowed to expose the getter:
public TOutput Something { get; }
Which alleviates the above problem
Bar is BaseFoo<ExtendOutput, ExtendInput>, and CreateInstance() requires BaseFoo<baseOutput, baseInput> to be returned, so it can't return Bar which is BaseFoo<ExtendOutput, ExtendInput>.
Regardless ExtendOutput inherits baseOutput, when you inherit a generic class the inheritance is invariant.
Consider using interfaces with in and out generic modifiers:
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public interface IBaseFoo<out T1, out T2>
{
public void DoSmth();
}
public class Bar : IBaseFoo<ExtendOutput, ExtendInput>
{
public void DoSmth()
{
}
}
public class Test
{
public void Show()
{
}
private IBaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar();
}
}
Take the scenario
BaseA -> SubB -> SubSubC
Explanation: SubSubC class inherits SubB class. The SubB class inherits BaseA class
BaseA -> SubD -> SubSubE
Explanation: SubSubE class inherits SubD class. The SubB class inherits BaseA class
So..on..
So there are many class that has its grand parent class as BaseA . The BaseA class has some properties that are common to all the methods. ex: CustomerID, LastLogin, UniqueName etc.
This is how the class is designed in the service which I'm consuming.
My doubt is While calling the service methods, all the methods would expect a parameter of any SubSub class. Can anyone please tell me, is there any way if I could assign values to the properties of the BaseA in one place so that while creating the SubSub objects I did not need to fill the base properties each time?
I'm using C# as my language.
Code:
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
public void SendRequestToService1()
{
(new MyServiceObject()).ServiceMethod1(new SubSubC());
}
public void SendRequestToService2()
{
(new MyServiceObject()).ServiceMethod2(new SubSubE());
}
}
In the above code, in SendRequestToService1 and SendRequestToService2 , i need to initialise the base class properties CustomerId and UniqueName.
Ex:
(new SubSubC(){ CustomerId=2, UniqueName="XXBB" });
If there are many methods, I need to initialize these properties each time for their respective classes. Is there a way I can initialize the base properties CustomerId and UniqueName in one place so that the inheriting classes(SubSubC,SubSubE here) no need to initialize when their objects are created?
Are you looking for the following functionality?
//dummy class replacing the service object and it's methods
public class MyServiceObject
{
public void ServiceMethod1(SubSubC param)
{ }
public void ServiceMethod2(SubSubE param)
{ }
}
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
//declare the SubSub objects
//SubSubC subSubC;
//SubSubE subSubE;
BaseA baseA;
public MyMain()
{
//assign the values to each class in the MyMain contrsuctor
baseA = new BaseA { CustomerId = 2, UniqueName = "XXBB" };
}
public void SendRequestToService1()
{
var subSub=new SubSubC();
(new MyServiceObject()).ServiceMethod1(Initialize(subSub));
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
(new MyServiceObject()).ServiceMethod2(Initialize(subSub));
}
private T Initialize<T>(T subSub) where T:BaseA
{
subSub.CustomerId = baseA.CustomerId;
subSub.UniqueName = baseA.UniqueName;
return subSub;
}
}
class Program
{
static void Main(string[] args)
{
MyMain myMain = new MyMain();
myMain.SendRequestToService1();
myMain.SendRequestToService2();
}
}
Are you asking about calling base constructors? If so:
class SubSubC : SubB
{
public object CProperty { get; private set; }
public SubSubC(object cProperty, string bProperty, int id) : base(bProperty, id)
{
CProperty = cProperty;
}
}
class SubB : BaseA
{
public string BProperty { get; private set; }
public SubB(string bProperty, int id) : base(id)
{
BProperty = bProperty;
}
}
class BaseA
{
public int ID { get; private set; }
public BaseA(int id)
{
ID = id;
}
}
Or are you asking about initializing objects in a method? If so (assume the setters are public in the following code, unlike in the preceding):
void SetSubSubCProperties(SubSubC c, object cProperty, string bProperty, int id)
{
c.CProperty = cProperty;
SetSubBProperties(c, bProperty, id);
}
void SetSubBProperties(SubB b, string bProperty, int id)
{
b.BProperty = bProperty;
SetBaseAProperties(b, id);
}
void SetBaseAProperties(BaseA a, int id)
{
a.ID = id;
}
Ok, Alex Filipovici's answer, it looks like you want to initialize an instance of a derived class by copying the base class properties from an instance of a different derived class. In that case, to reduce the duplication in Alex's answer, you can do this:
void Initialize(BaseA source, BaseA target)
{
target.CustomerID = source.CustomerID;
target.UniqueName = source.UniqueName;
}
Then, to modify his example:
public void SendRequestToService1()
{
var subSub = new SubSubC();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod1(subSub);
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod2(subSub);
}
Not sure I understand your question.
public class A {
public int ID { get; set; }
}
public class B : A {
}
you can do B b = new B() and then b.ID = 12.
Or, if you have a method that gets a parameter of type A in your service you can change the value in the same way.
public void doSomething(A a) {
a.ID = 12;
}
and call the method with instances of B - doSomething(new B())