I need to execute derived class constructor before base class constructor.
I am attaching code which is using virtual object in base class which need to be initialised in derived class. We decide type of virtual object in derived class and then assign values to that object once we have type of that object.
How could I call derived class constructor before base class constructor in this scenario.
public class BaseClass : UserControl, INotifyPropertyChanged
{
public Path ConnIn;
public Path ConnOut;
public virtual ObjectBase BaseObject { get; set; }
public void BaseClass(XmlElementConfig config)
{
this.BaseObject.Title = config.Title;
this.BaseObject.GroupID = config.GroupID;
}
}
public partial class DerivedClass : CanvasBase
{
private Audio_MonitorAction audio_objectAction;
public override ObjectBase BaseObject
{
get { return audio_objectAction; }
set
{
audio_objectAction = (Audio_MonitorAction)value;
NotifyPropertyChanged();
}
}
public DerivedClass(XmlElementConfig config) : base(config)
{
InitializeComponent();
audio_objectAction = new Audio_MonitorAction(createGuid);
}
}
"execute derived class constructor before base class constructor" is impossible
if possible, move initialization into BaseObject property (why should it be virtual?)
public class BaseClass : UserControl, INotifyPropertyChanged
{
public Path ConnIn;
public Path ConnOut;
private ObjectBase baseObject;
public ObjectBase BaseObject
{
get { return baseObject; }
set
{
baseObject = value;
if (baseObject != null)
{
baseObject.Title = config.Title;
baseObject.GroupID = config.GroupID;
}
NotifyPropertyChanged();
}
}
XmlElementConfig config;
public void BaseClass(XmlElementConfig config)
{
this.config = config;
}
}
public partial class DerivedClass : CanvasBase
{
private Audio_MonitorAction audio_objectAction;
public DerivedClass(XmlElementConfig config) : base(config)
{
InitializeComponent();
BaseObject = audio_objectAction = new Audio_MonitorAction(createGuid);
}
}
public class BaseClass : UserControl, INotifyPropertyChanged
{
public Path ConnIn;
public Path ConnOut;
public virtual ObjectBase BaseObject { get; set; }
public void BaseClass(XmlElementConfig config)
{
InitBase(config);
}
protected void InitBase(XmlElementConfig config)
{
if (BaseObject != null)
{
BaseObject.Title = config.Title;
BaseObject.GroupID = config.GroupID;
}
}
}
public DerivedClass(XmlElementConfig config) : base(config)
{
InitializeComponent();
audio_objectAction = new Audio_MonitorAction(createGuid);
InitBase(config);
}
Alternatively you can do in BaseClass call to virtual function and override it in derived class.
public class BaseClass : UserControl, INotifyPropertyChanged
{
public Path ConnIn;
public Path ConnOut;
public virtual ObjectBase BaseObject { get; set; }
public void BaseClass(XmlElementConfig config)
{
InitDerivedClass();
if (BaseObject != null)
{
BaseObject.Title = config.Title;
BaseObject.GroupID = config.GroupID;
}
}
protected virtual void InitDerivedClass() {}
}
public partial class DerivedClass : CanvasBase
{
private Audio_MonitorAction audio_objectAction;
public override ObjectBase BaseObject
{
get { return audio_objectAction; }
set
{
audio_objectAction = (Audio_MonitorAction)value;
NotifyPropertyChanged();
}
}
protected override ObjectBase InitDerivedClass
{
audio_objectAction = new Audio_MonitorAction(createGuid);
}
public DerivedClass(XmlElementConfig config) : base(config)
{
InitializeComponent();
}
}
Related
For background I mainly program in Java and am trying to work with/learn generics in a C# project and got stuck.
Here is my problem. From the main method you can see I am trying to set the soldiers task, but I'm getting the error,
cannot convert from 'TaskHeal' to 'TaskBase<SoldierBase>'
It seems that this cast should work as TaskHeal is a child of TaskBase, but it doesn't. Here is my complete code:
public class Main {
static void main(string[] args) {
SoldierMedic myMedic = new SoldierMedic();
myMedic.setTask(new TaskHeal(myMedic)); // Problem!
}
}
public class SoldierBase {
private TaskBase<SoldierBase> currentTask;
public int status;
public void setTask(TaskBase<SoldierBase> newTask) {
this.currentTask = newTask;
}
}
public class SoldierMedic : SoldierBase {
public int healRate = 45;
}
public abstract class TaskBase<T> where T : SoldierBase {
protected T soldier;
public TaskBase(T unit) {
this.soldier = unit;
this.soldier.status = 1;
}
public abstract void preformTask();
}
public class TaskHeal : TaskBase<SoldierMedic> {
public TaskHeal(SoldierMedic unit) : base(unit) { }
public override void preformTask() {
this.soldier.healRate++;
}
}
If you don't mind having an additional base, non-generic class for TaskBase and SoldierBase, you could do this:
class Program
{
static void Main(string[] args)
{
var myMedic = new SoldierMedic();
myMedic.setTask(new TaskHeal(myMedic)); // Problem!
}
}
public class SoldierBase
{
public int status;
}
public class SoldierBase<T> : SoldierBase where T : SoldierBase
{
private TaskBase currentTask;
public void setTask(TaskBase newTask)
{
this.currentTask = newTask;
}
}
public class SoldierMedic : SoldierBase<SoldierMedic>
{
public int healRate = 45;
}
public abstract class TaskBase
{
}
public abstract class TaskBase<T> : TaskBase where T : SoldierBase<T>
{
protected T soldier;
public TaskBase(T unit)
{
this.soldier = unit;
this.soldier.status = 1;
}
public abstract void preformTask();
}
public class TaskHeal : TaskBase<SoldierMedic>
{
public TaskHeal(SoldierMedic unit) : base(unit) { }
public override void preformTask()
{
this.soldier.healRate++;
}
}
If you want this to look more like c# (using properties, proper access modifiers and casing), you'd do something like this:
class Program
{
static void Main(string[] args)
{
var myMedic = new SoldierMedic();
myMedic.CurrentTask = new TaskHeal(myMedic); // Problem!
}
}
public class SoldierBase
{
public int Status { get; set; }
}
public class SoldierBase<T> : SoldierBase where T : SoldierBase
{
public TaskBase CurrentTask { get; set; }
}
public class SoldierMedic : SoldierBase<SoldierMedic>
{
public int HealRate { get; set; } = 45;
}
public abstract class TaskBase
{
}
public abstract class TaskBase<T> : TaskBase where T : SoldierBase<T>
{
protected T Soldier;
public TaskBase(T unit)
{
Soldier = unit;
Soldier.Status = 1;
}
public abstract void PerformTask();
}
public class TaskHeal : TaskBase<SoldierMedic>
{
public TaskHeal(SoldierMedic unit) : base(unit) { }
public override void PerformTask()
{
Soldier.HealRate++;
}
}
Please see this structure (from here):
public abstract class AbstractPage<T> where T : AbstractPageEmenetsMap, new()
{
protected readonly string url;
protected VendorInfo vendorInfo;
public AbstractPage(VendorInfo vendorInfo)
{
this.vendorInfo = vendorInfo;
this.url = this.vendorInfo.Url;
}
public void Navigate()
{
WebDriver.Driver.Navigate().GoToUrl(this.url);
}
protected T Map
{
get { return new T(); }
}
}
public abstract class AbstractPage<M, V> : AbstractPage<M>, ITest
where M : AbstractPageEmenetsMap, new()
where V : AbstractPageValidator<M>, new()
{
public AbstractPage(VendorInfo vendorInfo)
: base(vendorInfo) { }
public V Validate()
{
return new V();
}
public void Login();
{
throw new System.NotImplementedException();
}
public void Logout();
{
throw new System.NotImplementedException();
}
}
And i want to add interface with some operations
public interface ITest
{
void Login();
void Logout();
}
Now this is Son class:
public class GmailPage : AbstractPage<GmailPageElementsMap, GmailPageValidator>, ITest
{
public GmailPage() : base("http:...") { }
}
Class that holds all the elements:
public IWebElement EmailAddressTextBox
{
get
{
return WebDriver.WebDriverWait.Until(ExpectedConditions.ElementIsVisible(By.Id("identifierId")));
}
}
And validator:
public class GmailPageValidator : AbstractPageValidator<GmailPageElementsMap>
{
}
As you can see i implement ITest from my Gmail class but i don't received any compile error although i do not add this 2 interface methods (Login and Logout).
This is because those methods are implemented in the parent AbstractPage. If you want to force GmailPage (and all other derived classes) to implement Login() and Logout() declare them as abstract in the parent AbstractPage class
public abstract class AbstractPage<M, V> : AbstractPage<M>, ITest
where M : AbstractPageEmenetsMap, new()
where V : AbstractPageValidator<M>, new()
{
public AbstractPage(VendorInfo vendorInfo) : base(vendorInfo) { }
public V Validate()
{
return new V();
}
public abstract void Login();
public abstract void Logout();
}
And override in GmailPage
public class GmailPage : AbstractPage<GmailPageElementsMap, GmailPageValidator>
{
public GmailPage() : base("http:...") { }
public override void Login()
{
throw new System.NotImplementedException();
}
public override void Logout()
{
throw new System.NotImplementedException();
}
}
I have below object model with simple inheritance:
public class RuntimeApiManagerBase
{
}
public class CatalogRuntimeApiManagerBase : RuntimeApiManagerBase
{
public void Method1()
{
}
}
public class DocumentRuntimeApiManagerBase : RuntimeApiManagerBase
{
public void Method2()
{
}
public void Method3()
{
}
}
public class BaseObject
{
public BaseObject(RuntimeApiManagerBase runtimeApiMgr)
{
RuntimeApiMgr = runtimeApiMgr;
}
public RuntimeApiManagerBase RuntimeApiMgr { get; set; }
}
public class Catalog : BaseObject
{
public Catalog() : base(new CatalogRuntimeApiManagerBase())
{
}
}
public class Document : BaseObject
{
public Document() : base(new DocumentRuntimeApiManagerBase())
{
}
}
Now, I want to access RuntimeApiMgr Property's Methods based on exactly derived type. However, it displays nothing which is logical:
Catalog c1 = new Catalog();
// c1.RuntimeApiMgr. => No Method1
Document d1 = new Document();
// d1.RuntimeApiMgr. => No Method2 and Method3
Is that possible using different structure like Generics or something else?
Thanks for your time.
Use generics:
public class BaseObject<T>
where T : RuntimeApiManagerBase
{
public BaseObject(T runtimeApiMgr)
{
RuntimeApiMgr = runtimeApiMgr;
}
public T RuntimeApiMgr { get; set; }
}
public class Catalog : BaseObject<CatalogRuntimeApiManagerBase>
{
public Catalog() : base(new CatalogRuntimeApiManagerBase())
{
}
}
public class Document : BaseObject<DocumentRuntimeApiManagerBase>
{
public Document() : base(new DocumentRuntimeApiManagerBase())
{
}
}
In that case your c1.RuntimeApiMgr will be of the type CatalogRuntimeApiManagerBase and will have Method1
You can use RuntimeApiManagerBase as generic and have a type constraint where T must be a subclass of RuntimeApiManagerBase
public class BaseObject<T> where T : RuntimeApiManagerBase
{
public BaseObject(T runtimeApiMgr)
{
RuntimeApiMgr = runtimeApiMgr;
}
public T RuntimeApiMgr { get; set; }
}
public class Catalog : BaseObject<CatalogRuntimeApiManagerBase>
{
public Catalog() : base(new CatalogRuntimeApiManagerBase())
{
}
}
public class Document : BaseObject<DocumentRuntimeApiManagerBase>
{
public Document() : base(new DocumentRuntimeApiManagerBase())
{
}
}
Catalog c1 = new Catalog();
c1.RuntimeApiMgr.Method1();
Document d1 = new Document();
d1.RuntimeApiMgr.Method2();
Alternative to solution with generics is an old fashioned approach with casting.
Maybe something like this:
Catalog c1 = new Catalog();
(c1.RuntimeApiMgr as CatalogRuntimeApiManagerBase).Method1();
Document d1 = new Document();
(d1.RuntimeApiMgr as DocumentRuntimeApiManagerBase).Method2();
Or create new properties with the same name in Caltalog and Document classes:
public class Catalog : BaseObject
{
public Catalog() : base(new CatalogRuntimeApiManagerBase())
{
}
public new CatalogRuntimeApiManagerBase RuntimeApiMgr { get; set; }
}
I have the following classes:
BaseField:
public abstract class BaseField {
...
public BaseField()
{
}
public BaseField(E_FieldType fieldType)
{
_FieldType = fieldType;
}
}
TextField:
public class TextField : BaseField {
...
public TextField() : base(E_FieldType.Text)
{
}
}
DateField:
public class DateField : BaseField {
...
public DateField() : base(E_FieldType.Date)
{
}
}
And DataBlock class which should contain TextField or DateField:
public class DataBlock<T> : BaseBlock where T : BaseField, new() {
...
private T _Field;
public DataBlock(string name): base(name, E_BlockType.Data)
{
_Field = new T();
}
}
The following line works fine:
DataBlock<TextField> db = new DataBlock<TextField>("qwe");
But It is not possible to write this code:
public ObservableCollection<DataBlock<BaseField>> DataBlockList { get; set; }
public DataBlockViewModel()
{
DataBlockList = new ObservableCollection<DataBlock<BaseField>>();
DataBlockList.Add(new DataBlock<TextField>("qwe"));
DataBlockList.Add(new DataBlock<DateField>("asd"));
}
The error is:
'BaseField' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'T' in the generic type or
method 'DataBlock<T>'
Could you please advise how to solve the issue that I can create ObservableCollection<DataBlock<BaseField>> collection?
I can remove new() from public class DataBlock<T> : BaseBlock where T : BaseField and
public DataBlock(string name): base(name, E_BlockType.Data)
{
//_Field = new T();
}
In this case I can create DataBlockList = new ObservableCollection<DataBlock<BaseField>>();
but it is not possible to write:
DataBlockList.Add(new DataBlock<TextField>("qwe"));
DataBlockList.Add(new DataBlock<DateField>("asd"));
There are 2 ways to get rid of the error:
1) You can make the class BaseField non-abstract
public abstract class BaseField {
...
public BaseField()
{
}
public BaseField(E_FieldType fieldType)
{
_FieldType = fieldType;
}
}
2) Pass the new BaseField object as constructor parameter to DataBlock and remove the new() constraint.
public class DataBlock<T> : BaseBlock where T : BaseField {
...
private T _Field;
public DataBlock(string name, T field): base(name, E_BlockType.Data)
{
_Field = field;
}
}
I'm trying to create an abstract generic class which inherits from another abstract generic class.
Here's what I have so far
public abstract class BaseClass {
public long Id { get; private set; }
public BaseClass(long id) {
this.Id = id;
}
}
public abstract class BaseClass<T> : BaseClass where T : BaseClass {
protected BaseClass(long id)
: base(id) {
}
public static T Get(long id) {
T item;
return TryGet(id, out item) ? item : default(T);
}
public static bool TryGet(long id, out T item) {
item = null; // This is where I call the cache but for this example I've removed so it will compile
if (item != null) { return true; }
else {
// Call TryGetFallback method
return false;
}
}
protected abstract T TryGetFallback(long id);
}
public abstract class DerivedClass : BaseClass<DerivedClass> {
public String Name { get; private set; }
public DerivedClass(long id, String name)
: base(id) {
this.Name = name;
}
}
public class DerivedDerivedClass : DerivedClass {
protected override DerivedDerivedClass TryGetFallback(long id) {
// Handle the try get fallback
}
}
The TryGetFallback method on the DerivedDerivedClass causes a compiler error.
First you need to fix your BaseClass<T> implementation to not have a recursive type constraint.
public abstract class BaseClass<T> : BaseClass where T : new() {
//snip
}
Then you can use it in your derived class, for example I will make it use int for the generic type parameter:
public abstract class DerivedClass : BaseClass<int> {
//snip
}
And now if you compile it will warn you that 'DerivedDerivedClass' does not implement inherited abstract member 'BaseClass<int>.TryGetFallback(long)'
Thanks for the tips #DavidG it's helped me to solve the problem with the following code
public abstract class BaseClass {
public long Id { get; private set; }
public BaseClass(long id) {
this.Id = id;
}
}
public abstract class BaseClass<T> : BaseClass where T : BaseClass<T>, new() {
protected BaseClass(long id) : base(id) { }
public static T Get(long id) {
T item;
return TryGet(id, out item) ? item : default(T);
}
public static bool TryGet(long id, out T item) {
item = null; // Try to get item from cache here
if (item != null) { return true; }
else {
T obj = new T();
item = obj.TryGetFallback(id);
return item != null;
}
}
protected abstract T TryGetFallback(long id);
}
public abstract class DerivedClass<T> : BaseClass<T> where T : DerivedClass<T>, new() {
public String Name { get; private set; }
public DerivedClass() : base(0) { }
public DerivedClass(long id, String name)
: base(id) {
this.Name = name;
}
protected abstract override T TryGetFallback(long id);
}
public class DerivedDerivedClass : DerivedClass<DerivedDerivedClass> {
public DerivedDerivedClass() {
}
protected override DerivedDerivedClass TryGetFallback(long id) {
throw new NotImplementedException();
}
}