Just as title says, how to fire property when I do propertyList.Add(something)
So code is:
private List<string> _SomeStrings;
public List<string> SomeStrings
{
get
{
return _SomeStrings;
}
set
{
_SomeStrings = value;
}
odAdd //this is what I need but do not know how to do it
}
You can either use a built in type such as ObservableCollection; examples here and here. MSDN page.
You could also create a new class that derives from List, and overloads the functions you wish to hook.
class ListWithAdd<T> : List<T>
{
public new void Add(T item)
{
base.Add(item);
DoStuff();
}
}
Create a custom generic list, create a event which will be fired when an item is added in the list.
like this:
namespace ConsoleApplication2
{
public delegate void OnAddEventHandler(object item);
public class AddEventArgs : EventArgs
{
public object item { get; set; }
}
public class MyList<T> : List<T>
{
public event OnAddEventHandler OnAdd;
public new void Add(T item)
{
base.Add(item);
if (OnAdd != null)
{
OnAdd(item);
}
}
}
class Program
{
static void Main(string[] args)
{
MyList<string> lst = new MyList<string>();
lst.OnAdd += (item) => {
Console.WriteLine("new item added: " + item);
};
lst.Add("test");
Console.ReadLine();
}
}
}
here's fiddle for you: https://dotnetfiddle.net/tc5Mq1
Look into observablecollection https://learn.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1?view=netframework-4.7.2
Related
Consider this following code:
public interface IStackable {
Item Item;
int Amount;
}
// I have an Item data
public class Item {
private string _name;
private string _description;
}
// composite pattern: adding amount to item data
public class StackableItem : IStackable {
private Item _item;
private int _amount;
public Item Item => _item;
public int Amount => _amount;
public void AddAmount(int amount) {
this._amount += amount;
}
// *How to make this conform to interface?
// public void AddItem(StackableItem item) {}
public void AddItem(IStackable stackable) {
this._amount += stackable.GetAmount();
}
}
// composite pattern: adding amount to item data
public class UniqueItem : IStackable {
private List<Item> _items;
public Item Item => _items.First();
public int Amount => _items.Count;
public void AddItem(Item item) {
_items.Add(item);
}
// *How to make this conform to interface?
// public void AddItem(UniqueItem item) {}
public void AddItem(IStackable stackable) {
_items.Add() // how am I supposed to resolve this?
// pseudo code:
// for every item in stackable (but it has to be uniqueitem),
// add every item from stackable to this object;
// then I need to destroy that stackable object
}
}
I think it would be bad to add AddItem(IStackable stackable) to the interface. Even if I did, I can't make method that works as intended.
The only way I can think is to cast Stackable to Unique Items first, but I believe that's not a good way also.
*I think the best way is to add a method with different signature conforms to interface,
So How to add method with different signature, but known type, conforms to interface?
Edit:
StackableItem example: Potion x10
UniqueItem example: 3 gun with each have different ammo
IStackable is for the UI, so that UI don't need to know their implementation and still can show the Item and Amount accordingly, (and neatly become one Item slot regardless of implementation)
Yes you could simply do
public interface IStackable
{
Item GetItem();
int GetAmount();
void AddItem(int amount);
void AddItem(IStackable item);
}
My guess what you wanted to ask is: You want to be sure that only StackableItem can be passed if this method is implemented in StackableItem.
I see basically two options:
Runtime check by casting. Either using is
public void AddItem(IStackable stackable)
{
if(stackable == null)
{
Debug.LogError("Null passed!");
return;
}
if(stackable is StackableItem item)
{
this._amount += item.GetAmount();
}
else
{
Debug.LogError($"Unexpected type {stackable.GetType} passed but expected {typeof(StackableItem)}");
}
}
or as
public void AddItem(IStackable stackable)
{
if(stackable == null)
{
Debug.LogError("Null passed!");
return;
}
var item = stackable as StackableItem;
if(item != null)
{
this._amount += item.GetAmount();
}
else
{
Debug.LogError($"Unexpected type passed! Expected {typeof(StackableItem)}");
}
}
Use a generic interface
public interface IStackable
{
Item GetItem();
int GetAmount();
void AddItem(int amount);
}
public interface IStackable<T> : IStackable where T : IStackable
{
void AddItem(T item);
}
and let your class inherit
public class StackableItem : IStackable<StackableItem>
{
...
public void AddItem(StackableItem stackable)
{
_amount += stackable.GetAmount();
}
public void AddItem (int amount)
{
_amount += amount;
}
}
I have a static array list in class called cart, is there a way to implement event listener to be used by other classes?
I am new to c# tried to understand PropertyChangedEventHandler with no success.
The arraylist and property are initialized as below:
private static ArrayList cartList = new ArrayList();
public static ArrayList CartList
{
get { return cartList; }
set
{
cartList = value;
}
}
Edit:
Altered #KMC code to work with List by hiding base methods:
public class ListOfProducts : List<Product>
{
public void Add(Product obj)
{
base.Add(obj);
this.OnChange();
}
public void UpdateLast(Product obj)
{
base[base.Count - 1] = obj;
this.OnChange();
}
public void Remove(Product obj)
{
base.Remove(obj);
this.OnChange();
}
public void Clear()
{
base.Clear();
this.OnChange();
}
public event EventHandler Change;
protected void OnChange()
{
if (this.Change != null)
{
this.Change(this, new EventArgs() { });
}
}
}
the ArrayList type is extensible. you can override the add and remove methods and fire some events.
for ex)
public class NewArrayList : ArrayList
{
public event EventHandler Change;
public override int Add(object value)
{
var result = base.Add(value);
this.OnChange();
return result;
}
public override void Remove(object obj)
{
base.Remove(obj);
this.OnChange();
}
protected void OnChange()
{
if (this.Change != null)
{
this.Change(this, new EventArgs() { });
}
}
}
public static class program
{
static void Main(string[] args)
{
var list = new NewArrayList();
list.Change += delegate (object sender, EventArgs arg) {
Console.WriteLine("collect changed {0}", list.Count);
};
list.Add(1);
list.Add(2);
list.Remove(2);
}
}
since the ArrayList needs to send some type of message (event) and I'm not sure who will be receiving it, I'll leave it up to you.
You can't get notified when count of elements in ArrayList changes nor when any element changes.
ArrayList and most other standard collections in .Net Framework like List<T>, Dictionary and arrays (except specialized classes like ObservableCollection in WPF) do not provide notification on items added/removed. You can easily check that by looking at MSDN entry for corresponding class and see if it implements INotifyCollectionChanged and/or INotifyPropertyChanged. I.e. ArrayList only implements IList, ICollection, IEnumerable, ICloneable and no notification interfaces.
If you need notification of such change you should create your own class with such notification or use ObservableCollection.
Side note: please consider using List<T> instead of non-generic ArrayList- ArrayList vs List<> in C#.
I need to make alternative to List<> class where I will have 4 methods... Two for adding int items, one from front, other from behind and two for deleting, one from front and other from behind as well. My class should not inherit anything.
Something like this...
public class MyList
{
public void AddItemsFront(int pItem)
{
}
public void AddItemsBehind(int pItem)
{
}
public void DeleteItemsFront(int pItem)
{
}
public void DeleteItemsBehind(int pItem)
{
}
}
You could hold an instance of a List<T> in a field, List<T> has already these methods:
public class MyList<T>
{
private List<T> _TheList;
public MyList()
{
_TheList = new List<T>();
}
public List<T> TheList { get { return _TheList; } set { _TheList = value; } }
public void AddItemFront(T pItem)
{
TheList.Insert(0, pItem);
}
public void AddItemBehind(T pItem)
{
TheList.Add(pItem);
}
public void DeleteItemFront()
{
TheList.RemoveAt(0);
}
public void DeleteItemBehind()
{
TheList.RemoveAt(TheList.Count - 1);
}
}
Since it's a generic class you could also use it for different types than int.
var myList = new MyList<int>();
myList.AddItemFront(1);
Create a class that's got a data member of the correct List<> type, and implement your methods by calling the appropriate methods on the List<> data member. You will want your delete operations to return the object they removed from the list.
This is often referred to as the Adapter pattern. Wikipedia has a page on it.
I've found some code that is a bit long in a method:
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
if (item is Son) {
...SOME CODE...
}
else if (item is Daughter) {
...MORE CODE...
}
}
}
}
Because of this big if-else block, the method is quite large, and smells as bad design (OOP-wise).
I've tried to come up with something a bit more polymorphic, taking advantage of method-overloading via different type-paramaters, such as:
class MainClass
{
private static void DoSomething (Son son)
{
Console.WriteLine ("Son");
}
private static void DoSomething (Daughter daughter)
{
Console.WriteLine ("Daughter");
}
private static void DoSomething (Parent parent)
{
Console.WriteLine ("Parent");
}
private void Iterate(IEnumerable<Parent> list)
{
foreach (var item in list) {
DoSomething (item);
}
}
}
But this doesn't work because it always prints "Parent", so I guess I would need to downcast manually, which defeats the point a bit, and would not look elegant.
One last point: if you are tempted to recommend me to put the implementation of DoSomething in the derived classes of Parent, that is not possible, because of dependency problems (the assembly where these 3 classes live cannot have dependencies on some things that the SOME CODE and MORE CODE is calling).
So what would be the best approach to refactor this? Thanks!
There are several ways to do this asides from the switch statement you've already identified (which definitely gets clunky with more than a couple of types involved).
First of all, if you aren't likely to add subtypes, but you are likely to add other things to do with the subtypes, you can use the Visitor Pattern to mimic double dispatch.
class Parent
{
public abstract void Accept(IChildVisitor visitor);
}
class Son : Parent
{
public override void Accept(IChildVisitor visitor)
{
visitor.Visit(this);
}
}
class Daughter : Parent
{
public override void Accept(IChildVisitor visitor)
{
visitor.Visit(this);
}
}
interface IChildVisitor
{
Visit(Son son);
Visit(Daughter daughter);
}
class SomeCodeChildVisitor : IChildVisitor
{
public Visit(Son son)
{
...SOME CODE...
}
public Visit(Daughter daughter)
{
...SOME CODE...
}
}
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
item.Accept(new SomeCodeChildVisitor());
}
}
}
You can also use a Dictionary<Type,Action>
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
// If you don't actually need a reference to the child
private void IDictionary<Type, Action> map =
new Dictionary<Type, Action>()
{
{ typeof(Son), () => ...SOME CODE... }
{ typeof(Daughter), () => ...SOME CODE... }
};
// If you do need a reference to the child
private void IDictionary<Type, Action<Parent>> otherMap =
new Dictionary<Type, Action<Parent>>()
{
{ typeof(Son), x => (Son)x. ...SOME CODE... }
{ typeof(Daughter), y => (Daughter)x. ...SOME CODE... }
};
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
// either
map[item.GetType()]();
// or
otherMap[item.GetType()](item);
}
}
}
You can also use the dynamic keyword
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Parent item in list) {
Visit((dynamic)item);
}
}
private void Visit(Son son)
{
...SOME CODE...
}
private void Visit(Daughter daughter)
{
...SOME CODE...
}
}
You can also just filter the types straight out of your collection with Linq (especially if you only care about some subtypes and not others, e.g. if you're iterating through a Controls collection and you only care about Buttons)
class Parent { }
class Son : Parent { }
class Daughter : Parent { }
class MainClass
{
private void Iterate(IEnumerable<Parent> list)
{
foreach (Daughter daughter in list.OfType<Daughter>()) {
...SOME CODE...
}
}
}
In C# I generally recommend the dictionary approach, but any will do in a pinch.
The best situation is to move DoSomething() method to the classes. If not possible, maybe you still can use conditionals to polymorphism, but with the decorator pattern. In this case you can
Define an abstract class with an abstract method DoSomething(). Let's call it FamilyDecorator. It's a good idea to create a constructor which receives a Parent in his parameter, so you can save it as a protected variable (that means: visible to all of the derived classes).
Declare one decorator for each class on your assembly: ParentDecorator, SonDecorator, DaughterDecorator. These three classes inherit from FamilyDecorator and must override the DoSomething() method.
The trick is to create a method in the abstract class that returns one or another Decorator, based on type. That's the way you can separate which logic use on each case:
abstract class FamilyDecorator
{
protected Domain.Parent _member;
public abstract void DoSomething();
internal FamilyDecorator(Domain.Parent member)
{
_member = member;
}
public static FamilyDecorator GetDecorator(Domain.Parent item)
{
if(item.GetType() == typeof(Domain.Parent))
{
return new ParentDecorator(item);
}
else if (item.GetType() == typeof(Domain.Son))
{
return new SonDecorator(item);
}
else if (item.GetType() == typeof(Domain.Daughter))
{
return new DaughterDecorator(item);
}
return null;
}
}
class ParentDecorator : FamilyDecorator
{
internal ParentDecorator(Domain.Parent parent)
: base(parent)
{
}
public override void DoSomething()
{
Console.WriteLine("A parent");
}
}
class SonDecorator : FamilyDecorator
{
internal SonDecorator(Domain.Parent son)
: base(son)
{
this._member = son;
}
public override void DoSomething()
{
Console.WriteLine("A son");
}
}
class DaughterDecorator : FamilyDecorator
{
internal DaughterDecorator(Domain.Parent daughter)
: base(daughter)
{
}
public override void DoSomething()
{
Console.WriteLine("A daughter");
}
}
Then, in your Main class:
foreach (Parent item in list)
{
var decorator = FamilyDecorator.GetDecorator(item);
decorator.DoSomething();
}
This solution keeps the code very clean and takes advantage of polymorphism.
Edit
I don't think I like this solution because you're basically moving the
type checking from the foreach loop to the GetDecorator() method.
Polymorphism should allow you to do this without type checking
manually.
There is another solution, based on the same idea: to use reflection for the object construction.
In this case:
Instead of an abstract class you define an Interface that declares the DoSomething() method.
Now each decorator inherits from their corresponding class (Parent - ParentDecorator, Son - SonDecorator, etc.)
You need to change the constructors in the Decorator classes. They need to be public if you want to use reflection.
Finally, the GetDecorator() method just search for the derived class in the assembly. If found, it returns the decorator.
namespace FamilyNamespace
{
interface IFamily
{
void DoSomething();
}
class ParentDecorator : Domain.Parent, IFamily
{
private Domain.Parent _member;
public ParentDecorator(Domain.Parent parent)
{
this._member = parent;
}
public void DoSomething()
{
Console.WriteLine("A parent");
}
}
class SonDecorator : Domain.Son, IFamily
{
private Domain.Parent _member;
public SonDecorator(Domain.Parent son)
{
this._member = son;
}
public void DoSomething()
{
Console.WriteLine("A son");
}
}
class DaughterDecorator : Domain.Daughter, IFamily
{
private Domain.Parent _member;
public DaughterDecorator(Domain.Parent daughter)
{
this._member = daughter;
}
public void DoSomething()
{
Console.WriteLine("A daughter");
}
}
}
Then in your Main class:
static FamilyNamespace.IFamily GetDecorator(Domain.Parent item)
{
var baseType = item.GetType();
var derivedType = Assembly.GetExecutingAssembly().GetTypes().Where(m => m != baseType && baseType.IsAssignableFrom(m));
if (derivedType.Any())
{
return (FamilyNamespace.IFamily)Activator.CreateInstance(derivedType.First(), new object[] { item });
}
return null;
}
... and the Main method:
foreach (Domain.Parent item in list)
{
var decorator = (FamilyNamespace.IFamily)GetDecorator(item);
decorator.DoSomething();
}
Greetings
I have a List<MyClass> with a N numbers of items. I process with the following code
foreach (var item in myList)
{
ThreadPool.QueueUserWorkItem(DoWorkWithItem, item);
}
private void DoWorkWithItem(object threadContext)
{
///...
}
but i need get report what item was proccessed, where i can get a Event or something for this task
create event and call it after threat iteration finished, like this:
public class ClassWithDelegate
{
public delegate void ProgressReportEventHandler();
public static ProgressReportEventHandler ProgressReport { get; set; };
private void DoWorkWithItem(object threadContext)
{
// angry code
if (ProgressReport != null)
ProgressReport();
}
}
public class Subscriber
{
public Subscriber()
{
ClassWithDelegate.ProgressReport += ProgressReport;
}
public void ProgressReport()
{
//todo
}
}
or use BackgroundWorker, it has this event