We have an exercise about inheritance in c#. Now my problem is that what will i put in the question mark and in the if statement to know that the program passed a Person class or an Animal class or any class under InventoryApplication namespace. :)
private void AddButton_Click(object sender, EventArgs e)
{
Logic_Layer.Logic logic = new Logic();
//logic.Add<Person>();
}
namespace Logic_Layer
{
public class Logic
{
public void Add<InventoryApplication>() where InventoryApplication : ?
{
//if { }
}
public void delete() { }
public void edit() { }
public void search() { }
public void searchAll() { }
}
}
You can't use such a statement in the constraint. However, later in the method you can do this:
if (typeof(myObject).Namespace == "InventoryApplication")
{
...
}
What would be better is if the classes you want to test for (Animal, Person etc.) would implement an interface (say, IMyInterface).
For example:
void Add<T>(<T> param) where T : IMyInterface {/*...*/}
Related
Lately I've stuck with some project. What I want to do?
I have some number of classes. Let's say something like that:
public class ActionEventArgs : EventArgs
{
public Creature actor;
}
public class LocationEventArgs : ActionEventArgs
{
public Location loc;
}
public class Action
{
public virtual void Do(object sender, ActionEventArgs e)
{
//... do something with it;
}
}
public class LocationAction : Action
{
public override void Do(object sender, LocationEventArgs e) // error, signatures differs
{
//... do something with it;
}
}
public class MainClass
{
public Action a { get; protected set; }
public void InitAction()
{
a = new LocationAction();
}
public void DoAction(Creature actor, Location location)
{
a.Do(this, new LocationEventArgs() { actor = actor, loc = location });
}
}
Well, it didn't work because of different methods signatures. Ok.
Of course, I can use something like class checks like:
public class LocationAction : Action
{
public override void Do(Action sender, ActionEventArgs e)
{
if (e is LocationEventArgs) throw new ArgumentException("e must be LocationEventArgs");
//... do something with it;
}
}
But I don't really like it, because it's only runtime thing. So, the question is: how to do this properly? Is there a way?
I think you want to use generics:
public class Action<TArg> where TArg : ActionEventArgs
{
public virtual void Do(object sender, TArg e)
{
// can access 'e.actor'
}
}
public class LocationAction : Action<LocationEventArgs>
{
public override void Do(object sender, LocationEventArgs e)
{
// can access 'e.actor' and 'e.loc'
}
}
I think what you are willing to do goes against the principle itself. You can't override and change the parameters. maybe add a
public override void Do(object sender, LocationEventArgs e) // error,
signatures differs
{
//... do something with it;
}
in your action class ?
I create child objects (Customer, Product, ...) and invoke method ApplyChange in parent class (AggregateRoot), from that method I would like to call method Apply in child class for passed event. Is it possible using reflection or I should change something?
public abstract class AggregateRoot
{
public void ApplyChange(IEvent #event)
{
Apply(#event); // how to call this method?
}
}
public class Customer : AggregateRoot
{
private void Apply(CustomerCreatedEvent e)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
public class Product : AggregateRoot
{
private void Apply(ProductCreatedEvent e)
{
Console.WriteLine("ProductCreatedEvent");
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
customer.ApplyChange(new CustomerCreatedEvent());
Product product = new Product();
product.ApplyChange(new ProductCreatedEvent());
}
}
Is it possible using reflection or I should change something?
I focused for now on the non-reflection, as IMO reflection should be the last resort here.
Option 1: abstract method
You could make Apply an abstract method en then you could call it from AggregateRoot.
e.g.
using System;
public abstract class AggregateRoot
{
public void ApplyChange(IEvent #event)
{
Apply(#event); // how to call this method?
}
protected abstract void Apply(IEvent e);
}
public class Customer : AggregateRoot
{
protected override void Apply(IEvent e)
{
if (e is CustomerCreatedEvent)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
}
public class Product : AggregateRoot
{
protected override void Apply(IEvent e)
{
if (e is ProductCreatedEvent)
{
Console.WriteLine("ProductCreatedEvent");
}
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
But please note, it has it downsides as:
methods needs to non-private
the should have the same parameter type for Apply. (IEvent parameter) - so I've added the type check inside the Apply methods.
Option 2: abstract method and generic AggregateRoot
Another option is to make AggregateRoot generic for the type IEvent, e.g. something like this.
using System;
public abstract class AggregateRoot<TEvent>
where TEvent : IEvent
{
public void ApplyChange(TEvent #event)
{
Apply(#event); // how to call this method?
}
protected abstract void Apply(TEvent e);
}
public class Customer : AggregateRoot<CustomerCreatedEvent>
{
protected override void Apply(CustomerCreatedEvent e)
{
Console.WriteLine("CustomerCreatedEvent");
}
}
public class Product : AggregateRoot<ProductCreatedEvent>
{
protected override void Apply(ProductCreatedEvent e)
{
Console.WriteLine("ProductCreatedEvent");
}
}
public interface IEvent
{
}
public class CustomerCreatedEvent : IEvent
{
}
public class ProductCreatedEvent : IEvent
{
}
Note I've changed also ApplyChange in this case.
If those things won't solve your problem, please elaborate what you are trying to archive, otherwise this will be a XY problem
So i'm trying to organize my functions into nested classes so i can call them like: "Player.Trigger_Functions.TakeDamage()" rather than calling it as such: "Player.TakeDamage()". I suppose it is a less efficient way to call the functions the way I'm suggesting but it would help separate the functions into distinct categories while remaining on the same file.
Here is some test code but i can't get it to compile online to see if it works.
(some of the functions need to be able to interact with each-other despite being in separate containers which i think is a problem)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Program
{
public class meme{
public int thicc = 0;
public oof nest1 = new oof();
public watermelone nest2 = new watermelone();
public class oof : meme
{
public void here(){
thicc++;
}
public void call(){
nest2.here();
System.Console.WriteLine("oof" + thicc);
}
}
public class watermelone : meme
{
public void here(){
thicc++;
}
public void call(){
nest1.here();
System.Console.WriteLine("watermelone" + thicc);
}
}
}
public static void Main(){
meme me = new meme();
me.nest1.call();//adding 1
me.nest2.call();//adding 1
System.Console.WriteLine("here is the current thicc value of the me class:" + me.thicc);
}
}
Ok yeah so this code wouldn't work at all, i didn't put that much thought into it but you get the idea of what i'm trying to accomplish.
You can use interfaces to break up the functionality of your class into related groups.
From this:
class Person
{
void sayHello() { }
void sayGoodbye() { }
void walkForward() { }
void walkBackward() { }
}
Refactor into this:
interface ISpeak
{
void sayHello();
void sayGoodbye();
}
interface IWalk
{
void walkForward();
void walkBackward();
}
class Person : ISpeak, IWalk
{
void ISpeak.sayHello() { }
void ISpeak.sayGoodbye() { }
void IWalk.walkForward() { }
void IWalk.walkBackward() { }
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
IWalk walk = person;
ISpeak speak = person;
speak.sayHello();
walk.walkForward();
}
}
Error in line : public virtual void BuyFavoriteStuff()
Error : Expected class, delegate, enm, interface, or struct
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LearnAbstractClass
{
class Program
{
static void Main(string[] args)
{
}
}
class Shopper
{
private int TotalSpent=0, CreditLimit=10;
public void ShopTillYouDrop()
{
while (TotalSpent < CreditLimit)
BuyFavoriteStuff();
}
}
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
class ArtStudent : Shopper
{
public override void BuyFavoriteStuff()
{
BuyArtSupplies();
BuyBlackTurtlenecks();
BuyDepressingMusic();
}
private void BuyBlackTurtlenecks()
{}
private void BuyDepressingMusic()
{}
private void BuyArtSupplies()
{}
}
class EngineeringStudent : Shopper
{
public override void BuyFavoriteStuff()
{
BuyPencils();
BuyGraphingCalculator();
BuyPocketProtector();
}
private void BuyPencils()
{}
private void BuyGraphingCalculator()
{}
private void BuyPocketProtector()
{}
}
}
What is the wrong in implementation above?
your method:
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
it outside of the Shopper class
You have method that is outside of any class:
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
just move it to Shopper class.
The method BuyFavoriteStuff is not inside class
public virtual void BuyFavoriteStuff()
{
// No implementation here - we don’t know
// what our student likes to buy!
}
You should declare your method inside class.
I have used delegates to represent methods - but I now have many classes that have same methods (but different code in those methods).
Is there a way to delegate the entire class?
Pseudo code:
class myModelA
{
void update()
{
}
}
class myModelB
{
void update()
{
}
}
delegate class myModel;
if (x==1)
myModel = myModelA;
else
myModel = myModelB;
myModel.update();
I know I can delegate the "üpdate" method BUT in real world I have lots of methods and I would rather just simply delegate the class.
EDIT1 based on Jon Skeet's answer
BUT how do I declare a public variable? (non public variables compile OK)
public interface IModel
{
double myDouble; <<<< this gives an error
void Update();
}
public class MyModelA : IModel
{
public double myDouble;
public void Update() { ... }
}
public class MyModelB : IModel
{
public double myDouble;
public void Update() { ... }
}
No, in this case you don't want a delegate - you want an interface.
You create an interface which all of your classes implement:
public interface IModel
{
void Update();
}
public class MyModelA : IModel
{
public void Update() { ... }
}
public class MyModelB : IModel
{
public void Update() { ... }
}
Then:
IModel model;
if (x == 1)
{
model = new MyModelA();
}
else
{
model = new MyModelB();
}
model.Update();
As Jon Skeet, I think you need to use interfaces.
A little changed code from
http://www.dotnetperls.com/interface
using System;
interface IPerl
{
void Read();
}
class TestA : IPerl
{
public void Read()
{
Console.WriteLine("Read TestA");
}
}
class TestB : IPerl
{
public void Read()
{
Console.WriteLine("Read TestB");
}
}
class Program
{
static void Main()
{
IPerl perl = new TestA(); // Create instance.
perl.Read(); // Call method on interface.
}
}