How to set a property in class from a derived class - c#

I am not sure how this functions in C#.
I have a class:
public class FindIt()
{
}
public class FindItFrm()
{
private bool _amISet = false;
public FindItFrm()
{
}
public bool AmISet()
{
get { return _amISet; }
set { _amISet = value; }
}
}
And the class that I am working in has:
public class MyHelper() : FindIt
{
// Constructor
public MyHelper()
: base(new FindItFrm())
}
I want to set a property (AmISet) in the FindItFrm while inside the MyHelper class. How would I accomplish this?

Your code should look like this (in the future, please post working code for examples):
public class FindIt
{
// You need to let your derived class access the FindItFrm
protected FindItFrm Frm;
// Constructor needs to accept a FindItFrm
public FindIt(FindItFrm frm)
{
Frm = frm;
}
}
public class FindItFrm
{
private bool _amISet = false;
public bool AmISet
{
get { return _amISet; }
set { _amISet = value; }
}
}
public class MyHelper : FindIt
{
// Constructor
public MyHelper()
: base(new FindItFrm())
{
Frm.AmISet = true;
}
}

Related

Problem with generic class variables acess

Hello and sorry if I put the question or title incorrectly, I can’t formulate it in any way
I have a custom generic tiletype class with all information about the tile and in another script there is a bool CheckCondition();
I need to access the tileBase variable in the tileData class to use this in TileMap.GetTile<>() function
I have custom TileTypes class :
using System;
using UnityEngine;
using UnityEngine.Tilemaps;
public class TileTypes
{
[Serializable]
public class GroundTiles : TileData<GroundTileType>
{ }
[Serializable]
public class ObjectTiles : TileData<ObjectTileType>
{ }
public class TileData<T> : TileData
where T : Enum
{
public T TileType;
public override int TileTypeId { get { return Convert.ToInt32(TileType); } }
}
public abstract class TileData
{
public Sprite Sprite;
public Color Color;
public TileBase tileBase;
public Tile.ColliderType ColliderType;
public virtual int TileTypeId { get; }
public Item item;
}
}
have bool CheckCondition :
private bool CheckCondition(TileTypes.TileData tile, Item currentItem)
{
if(currentItem.type == ItemType.BuildingBlock)
{
if(!tile.tileBase)
{
return false;
}
}
else if(currentItem.type == ItemType.Tool)
{
if(tile.tileBase)
{
if(tile.item.actionType == currentItem.actionType)
{
return true;
}
}
}
return false;
}
and tryna do something like :
if(CheckCondition(TileMap.GetTile<TileTypes.TileData.tileBase>(pos), currentItem))

c# Factory for concrete implementation of generic base class

I have a Base class which is generic.
I have a concrete class which implements the base class.
How would I create a factory class/method for delivering different types of concrete classes?
Here an example:
public class ReceiverBase<T>
where T : IInterpreter
{ ... }
public class SpecialReceiver : ReceiverBase<OwnInterpreter> { ... }
public class ReceiverFactory<T>
where T : ReceiverBase<IInterpreter>, new()
public T Create(string type) {
switch(type) {
default:
return new SpecialReceiver();
}
}
}
The problem is that ReceiverBase seems not to be possible because the compiler only wants classes as Constraints, not interfaces.
And the second problem is that I cannot convert SpecialReceiver to T.
So is there a way to get this working?
=== EDIT: Added example according to first answer ===
public interface IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
public void Dispose()
{
throw new NotImplementedException();
}
public void DoSomething() { }
}
public abstract class ReceiverBase<T>
where T : IInterpreter
{
public T MyReceiver { get; set; }
internal abstract void Start();
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter, new()
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
MyReceiver = new T();
}
}
public class ReceiverFactory<T>
where T : IInterpreter, new()
{
public static ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The Problem is: MyReceiver.DoSomething(); will not work.
Additionally I would have to call the factory like this: ReceiverFactory<OwnInterpreter>.Create(""); I'd like to have it that way: ReceiverFactory.Create("SpecialReceiver");
You can use generic method in your factory:
class Program
{
static void Main(string[] args)
{
var own = ReceiverFactory.Create<OwnInterpreter>();
var other = ReceiverFactory.Create<OtherInterpreter>();
own.Start();
other.Start();
Console.ReadLine();
}
}
interface IInterpreter
{
void DoSomething();
}
class OwnInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Own"); }
}
class OtherInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Other"); }
}
abstract class ReceiverBase<T> where T: IInterpreter, new()
{
public T Interpreter { get; set; }
public ReceiverBase()
{
Interpreter = new T();
}
public void Start()
{
Interpreter.DoSomething();
}
}
class SpecialReceiver : ReceiverBase<OwnInterpreter> { }
class OtherReceiver : ReceiverBase<OtherInterpreter> { }
static class ReceiverFactory
{
private static Dictionary<string, object> factories = new Dictionary<string, object>();
static ReceiverFactory()
{
RegisterFactory(() => new SpecialReceiver());
RegisterFactory(() => new OtherReceiver());
}
public static void RegisterFactory<T>(Func<ReceiverBase<T>> factory) where T : IInterpreter, new()
{
factories.Add(typeof(T).FullName, factory);
}
public static ReceiverBase<T> Create<T>() where T : IInterpreter, new()
{
var type = typeof(T);
return ((Func<ReceiverBase<T>>)factories[type.FullName]).Invoke();
}
}
In fact, you do not need "new()" constraint here, since you use factories.
I suggest you to change your code to:
public class ReceiverBase<T> where T : IInterpreter
{
}
public interface IInterpreter
{
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
}
public class ReceiverFactory<T> where T : IInterpreter, new()
{
public ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The reason why you cannot just return T in your case is, that there is no implicit conversion between SpecialReceiver and ReceiverBase<IInterpreter>.
I was able to find a solution which suits my needs.
I've added another interface IReciver which defines the properties and members I really need. The factory method returns IReceiver so I can omit all binding issues whith generics. Sometimes it is just that easy. :)
public interface IInterpreter { }
public interface IReceiver
{
bool Enabled { get; set; }
}
public class OwnInterpreter : IInterpreter
{
public void DoSomething() { }
}
public abstract class ReceiverBase<T> : IReceiver
where T : IInterpreter, new()
{
public T MyReceiver { get; set; }
internal abstract void Start();
private bool _isEnabled;
public bool Enabled { get { return _isEnabled; } set { _isEnabled = value; OnEnable(value); } }
internal abstract void OnEnable(bool isEnabled);
protected ReceiverBase()
{
MyReceiver = new T();
}
}
public class SpecialReceiver : ReceiverBase<OwnInterpreter>
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
// just for testing puropses
MyReceiver = new OwnInterpreter();
}
internal override void OnEnable(bool isEnabled)
{
MyReceiver = isEnabled ? new OwnInterpreter() : null;
}
}
public class ReceiverFactory
{
public static IReceiver Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver();
}
}
}
public class Program
{
[STAThread]
public static void Main()
{
ReceiverFactory.Create("");
}
}

Convert object to generic abstract class

I got here a class that looks like this:
public abstract class SIBRegisterHardware2<T> : Register.IRegisterHardware<UInt16, UInt16> where T : IDevice
{
protected T open()
{
// connect to server and return device T
}
// ..
}
public class Device : SIBRegisterHardware2<IDevice>
{
// ..
}
and some derived classes:
internal class DeviceA: SIBRegisterHardware2<IDeviceA>
{
}
internal class DeviceB: SIBRegisterHardware2<IDeviceB>
{
}
Now I am looking for a solution that allows me this:
if(createDevA == true) {
Device<IDevice> devHandle = new DeviceA();
} else {
Device<IDevice> devHandle = new DeviceB():
}
The thing is that code like this produces errors like that:
Cannot implicitly convert type 'DeviceA' to 'SIBRegisterHardware2<IDevice>'
Is there a way that would allow me to abstract a template like this?
Something I tried out is creating another class that works with reflection:
public class DeviceX : SIBRegisterHardware2<IDevice>
{
private Register.IRegisterHardware<UInt16, UInt16> device = null;
private Type deviceType = null;
public DeviceX (String hwInterfaceClassName)
{
if (hwInterfaceClassName.Equals("DeviceA")) {
device = new DeviceA();
deviceType = device.GetType();
}
else if (hwInterfaceClassName.Equals("DeviceB")) {
device = new DeviceB();
deviceType = device.GetType();
}
}
public override String doSomething(int param)
{
return (String)deviceType.GetMethod("doSomething").Invoke(device, new object[] { param }); ;
}
}
but is that a neat design?
You should use the interface instead of abstract class for the SIBRegisterHardware2 type.
And than you can use Covariance in Generics:
public interface IDevice { }
public interface IDeviceA : IDevice { }
public interface IDeviceB : IDevice { }
public interface ISIBRegisterHardware2<out T> where T : class, IDevice
{
void DoSomething();
}
internal class DeviceA : ISIBRegisterHardware2<IDeviceA>
{
//...
}
internal class DeviceB : ISIBRegisterHardware2<IDeviceB>
{
//...
}
if (createDevA == true)
{
ISIBRegisterHardware2<IDevice> devHandle = new DeviceA();
}
else
{
ISIBRegisterHardware2<IDevice> devHandle = new DeviceB();
}
UPDATE 0
public interface ISIBRegisterHardware2<out T> : Register.IRegisterHardware<UInt16, UInt16> where T : class, IDevice
{
T Open();
}
public abstract class SIBRegisterHardware2<T> : ISIBRegisterHardware2<T> where T : class, IDevice
{
T ISIBRegisterHardware2<T>.Open()
{
return OpenInternal();
}
protected virtual T OpenInternal()
{
//Common logic to open.
}
}
internal class DeviceA : SIBRegisterHardware2<IDeviceA>
{
//...
}
internal class DeviceB : SIBRegisterHardware2<IDeviceB>
{
//...
}
ISIBRegisterHardware2<IDevice> devHandle;
if (createDevA == true)
{
devHandle = new DeviceA();
}
else
{
devHandle = new DeviceB();
}
devHandle.Open();

How to access different property value in derived class

I have ViewModelBase with a derived DerivedViewModel
ViewModelBase has DoSomething() which accesses AProperty
DerivedViewModel also uses DoSomething() but it needs to access a different object.
The reason behind this is that the ViewModel is used on a screen, as well as in a Dialog. When it is in a screen, it needs to access a particular entity, but when in a dialog, it needs to access a different entity.
Here it is, simplified, in code. If you run it, they both return A, instead of A, then B. So the question is, how to return A, then B?
class Program
{
static void Main(string[] args)
{
ViewModelBase bc = new ViewModelBase();
bc.DoSomething(); Prints A
DerivedViewModel dr = new DerivedViewModel();
dr.DoSomething(); Prints A, would like it to print B.
}
}
public class ViewModelBase {
private string _aProperty = "A";
public string AProperty {
get {
return _aProperty;
}
}
public void DoSomething() {
Console.WriteLine(AProperty);
}
}
public class DerivedViewModel : ViewModelBase {
private string _bProperty = "B";
public string AProperty {
get { return _bProperty; }
}
Override the property in derived class
public class ViewModelBase
{
private string _aProperty = "A";
public virtual string AProperty
{
get { return _aProperty; }
}
public void DoSomething()
{
Console.WriteLine(AProperty);
}
}
public class DerivedViewModel : ViewModelBase
{
private string _bProperty = "B";
public override string AProperty
{
get { return _bProperty; }
}
}
DerivedViewModel dr = new DerivedViewModel();
dr.DoSomething();//Prints B
Further take a look at Msdn Polymorphism

Override only Get accessor

I got an abstract class :
abstract class ClassBase
{
public abstract string Test { get; }
}
I want to derive it and by the way add a set accesor
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
set { _s = value; }
}
}
I can't do that because i may not override set
class ClassDerive2 : ClassBase
{
string _s;
public string Test
{
override get { return _s; }
set { _s = value; }
}
}
Syntax error
class ClassDerive3 : ClassBase
{
string _s;
public override string ClassBase.Test
{
get { return _s; }
}
public string Test
{
set { _s = value; }
}
}
Syntax error
Any Idea ???
thx
You cannot do exactly what you want to do but here is a workaround:
abstract class ClassBase
{
public abstract String Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
}
public void SetTest(String test)
{
this._s = test;
}
}
This will make Test only settable in ClassDerived via the public SetTest method. I know this is not as clean as using the property's setter but it is about as good as it's going to get.
If at first you have defined a read-only property in a type, you can't later change it to a read/write property in a derived class. That's simply how .NET works, and can't be changed.
If, on the other hand, you define an interface with a read-only property, you can later implement that interface in a class with a writable property.
If you'd like to share what you are trying to achieve, perhaps we can come up with a design that works and can compile :)
Another way:
abstract class ClassBase
{
public abstract string Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
protected void setTest(string s)
{
_s = s;
}
public override string Test
{
get { return _s; }
}
}
class ClassDerive2 : ClassDerive
{
public new string Test
{
get { return base.Test; }
set { setTest(value); }
}
}
class Program
{
static void Main(string[] args)
{
var cd2 = new ClassDerive2();
cd2.Test = "asdf";
Console.WriteLine(cd2.Test);
}
}
My first thought was also to implement it as an interface. If this fits in with your design, the following code will work:
public interface TestInterface
{
string TestProperty { get; }
}
public class TestClass : TestInterface
{
public string TestProperty
{
get { return "test"; }
set { string t = value; }
}
}
No you cant, sorry. It is by design, so it's the law.

Categories