Im trying to set a parent class property in child property setter.
I have one main class :User, which has a child class LIST ArrayPositions, which in turn has a child class list of ExpressionMember.
Whenever the property ExpressionMemValue in ExpressionMember class is set, i want to update it's parent class ArrayPosition aswell.
However the current solution does not update the corresponding parent.
Here's the code:
public List<User> users = new List<User>();
public class User
{
public string ImageName { get; set; }
private string _PartName = "";
public string PartName
{
get
{
return this._PartName;
}
set {
_PartName=value;
}
}
public List <ArrayPosition> ArrayPositions { get; set; }
public override string ToString()
{
return this.PartName.ToString();
}
}
public class ArrayPosition:User
{
public string myArrayPos = "";
public string PartId { get; set; }
public string ArrayPos
{
get
{
return this.myArrayPos;
}
set
{
this.myArrayPos = value;
}
}
public List<ExpressionMember> ExpressionMembers { get; set; }
}
public class ExpressionMember : ArrayPosition
{
public string ExpressionMem { get; set; }
public string MyExpressionMemValye="";
public string ExpressionMemValue
{
get
{
return MyExpressionMemValye;
}
set
{
MyExpressionMemValye = value;
// this.ArrayPos = value; //set parent value, this will not update it
}
}
}
It would appear that you need to not use inheritance and instead use composition which you are kind of already doing. Try doing this instead. It's not perfect by any means but I'm trying not to change your general strategy too much.
public class User
{
public string ImageName { get; set; }
private string _PartName = "";
public string PartName
{
get
{
return this._PartName;
}
set {
_PartName=value;
}
}
public List <ArrayPosition> ArrayPositions { get; set; }
public override string ToString()
{
return this.PartName.ToString();
}
}
public class ArrayPosition
{
public string myArrayPos = "";
public string PartId { get; set; }
public string ArrayPos
{
get
{
return this.myArrayPos;
}
set
{
this.myArrayPos = value;
}
}
public List<ExpressionMember> ExpressionMembers { get; set; }
}
public class ExpressionMember
{
private ArrayPosition _parentArrayPosition;
public string ExpressionMem { get; set; }
public string MyExpressionMemValye="";
public string ExpressionMemValue
{
get
{
return MyExpressionMemValye;
}
set
{
MyExpressionMemValye = value;
this._parentArrayPosition.ArrayPos = value;
}
public ExpressionMember(ArrayPosition parent) {
_parentArrayPosition = parent;
}
}
}
You are definitely not using inheritance and composition correctly. You are looking to build a tree of objects where the object itself has child objects. Something that might clarify things in your mind is instead of calling them child/parent classes, refer to them as sub/super classes in the case of inheritance and parent/child objects in the case of composition. A parent object is an instance of a class that contains another instance of a class (child object). A subclass inherits the members of another class.
Your inheritance is very strange. The exact responsibilities of your classes are not clear to me.
Apart from that, you could protect the property ExpressionMembers by making it read-only. Implement a new method to add or remove elements. Add an event (e.g. ExpressionMemValueChanged) to ExpressionMember . This event is triggered when an item is added. Whenever an element is added or removed you register/deregister ArrayPosition to/from this event. Inside the event handler you can then set your ArrayPos value.
(You can use an ObservableCollection for your ExpressionMembers and react to the CollectionChanged event instead of writing a getter/setter.)
Related
I want to practice code with DRY principle, but my method uses 2 different classes, classOneDTO and classTwoDTO.. They have different properties and I want to linked it with PRIMARYIDENTIFIER prop with both have the same..
How can I create a generic method to get the property that I want to query with Linq.
Updated: my purpose is to have a generic method that will query the PrimaryIdentifier and get the data to it whether they are using classOneDTO or classTwoDTO. Is there a way to have a single generic method to do this?
private void genericMethod<T>(List<T> workList, GridView grid, int columnNo)
{
if (workList.Any())
{
string CodeString = default;
// Want to dynamic get the properties in different class with PrimaryIDentifier property
// want to check if PrimaryIdentifier is NULL OR EMPTY
var getDataOne = workList.Cast<classOneDTO>().FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
// causing error because of the CAST if wrong type request
var getDataTwo = workList.Cast<classTwoDTO>().FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getDataOne != null || getDataTwo != null)
{
CodeString = (getDataOne != null) ? getDataOne.PrimaryIdentifier : getDataTwo.PrimaryIdentifier;
}
}
}
public class classOneDTO
{
public int PatientID { get; set; }
public string PrimaryIdentifier { get; set; }
public string FirstName{ get; set; }
// so oonnn...
}
public class classTwoDTO
{
public int EntryID { get; set; }
public string PrimaryIdentifier { get; set; }
public string Location{ get; set; }
// so oonnn...
}
All that you need is to make both your classes implement the same interface, i.e. IDTO:
public interface IDTO
{
string PrimaryIdentifier { get; set; }
}
Then you can tell the compiler to accept only types that implement your new interface:
private void GenericMethod<DTO>(List<DTO> workList, GridView grid, int columnNo)
where DTO: IDTO
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}
(Pay attention to the 2nd row)
Additionally, I also made minor adjustments to your class and method namings based on standard .Net naming convention.
Here's the full code:
public class Client
{
private void GenericMethod<DTO>(List<DTO> workList, GridView grid, int columnNo)
where DTO: IDTO
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}
}
public class ClassOneDTO : IDTO
{
public int PatientID { get; set; }
public string PrimaryIdentifier { get; set; }
public string FirstName { get; set; }
// so oonnn...
}
public class ClassTwoDTO : IDTO
{
public int EntryID { get; set; }
public string PrimaryIdentifier { get; set; }
public string Location { get; set; }
// so oonnn...
}
public interface IDTO
{
string PrimaryIdentifier { get; set; }
}
EDIT: as Johnathan Barclay correctly pointed out, there's actually no need to have a generic method if you don't need some more advanced logic there that you didn't show in your example.
private void GenericMethod(IEnumerable<IDTO> workList, GridView grid, int columnNo)
{
if (workList.Any())
{
string CodeString = default;
var getData = workList.FirstOrDefault(x => !string.IsNullOrEmpty(x.PrimaryIdentifier));
if (getData != null)
{
CodeString = getData?.PrimaryIdentifier;
}
}
}
I'm writing a tool which accesses a word document to prefill it with data. The document has a subset of custom document properties, each identified by a name, whose values are used to update fields in the document.
My ViewModel should both be able to initiate/update its instances from data of those document properties, aswell as write its values back and update the fields of the document.
Something like this:
class PersonVM : INotifyPropertyChanged
{
// properties
string Name { get; set; }
string PhoneNumber { get; set; }
// methods to get data or save data of this properties to or from the word document
void saveMyPropertyValuesToWord()
{
// …
}
void updateMyPropertiesFromWord()
{
// …
}
}
class ProjectVM : INotifyPropertyChanged
{
int ProjectNumber { get; set; }
PersonVM Manager { get; set; }
PersonVM Mechanic1 { get; set; }
PersonVM Mechanic2 { get; set; }
void saveMyPropertyValuesToWord()
{
Manager.saveMyPropertyValuesToWord();
Mechanic1.saveMyPropertyValuesToWord();
Mechanic2.saveMyPropertyValuesToWord();
// handle ProjectNumber etc.
}
void updateMyPropertiesFromWord()
{
Manager.updateMyPropertiesFromWord();
Mechanic1.updateMyPropertiesFromWord();
Mechanic2.updateMyPropertiesFromWord();
// handle ProjectNumber etc.
}
class CompanyVM : INotifyPropertyChanged
{
string Name { get; set; }
PersonVM Owner { get; set; }
ProjectVM Project1 { get; set; }
ProjectVM Project2 { get; set; }
// …
}
// …
}
Right now I have a class with static string properties for each document property that might be present in a word document from which I would like to load the data accordingly:
class WordUtils
{
// Company
static string CompanyName = "dp_CompanyName";
// Company.Owner
static string CompanyOwnerName = "dp_CompanyOwnerName";
static string CompanyOwnerPhone = "dp_CompanyOwnerPhone";
// Company.Project1
static string CompanyProject1Number = "dp_CompanyProject1Number";
// Company.Project1.Manager
static string CompanyProject1ManagerName = "dp_CompanyProject1ManagerName";
static string CompanyProject1ManagerPhone = "dp_CompanyProject1ManagerPhone";
// Company.Project1.Mechanic1
// … etc
}
Now back to implementing those PersonVM.saveMyPropertyValuesToWord() - I thought of something like this:
void saveMyPropertyValuesToWord()
{
Name = MyApp.MyWordDocument.GetCustomProperty(WordUtils.OwnerName);
}
but here I need to know on class Level exactly what instance of it this is called from (i.e. what PersonVM am I, Company.Owner or Project1.Manager or ?) in order to decide which WordUtils.Name I need to provide.
I'm not sure how this should be done, maybe make PersonVM abstract and make a new class for each role (which would again only have one instance of itself, not very pretty in my eyes)? I have also taken a short look at Attributes and expect those might be helpfull in this scenario. Maybe I am missing something obvious, but extensive search for a robust way to tackle this problem have been fruitless so far.
How about something like this:
class Property
{
public string Key { get; }
public string Value { get; set; }
public Property(string key) => Key = key;
}
interface IPropertyTree
{
IEnumerable<IPropertyTree> ChildNodes { get; }
IEnumerable<Property> Properties { get; }
}
class PersonVM : IPropertyTree
{
private readonly string prefix;
public PersonVM(string prefix)
{
Name = new Property(prefix + "Name" );
PhoneNumber = new Property(prefix + "PhoneNumber");
}
public Property Name { get; }
public Property PhoneNumber { get; }
public IEnumerable<IPropertyTree> ChildNodes => Enumerable.Empty<IPropertyTree>();
public IEnumerable<Property> Properties => new[] {Name, PhoneNumber};
}
static class PropertyTreeExtensions
{
public static void Update(this IPropertyTree self)
{
foreach (var property in self.Flatten().SelectMany(tree => tree.Properties))
{
property.Value = MyApp.MyWordDocument.GetCustomProperty(property.Key);
}
}
public static IEnumerable<IPropertyTree> Flatten(this IPropertyTree self)
{
var stack = new Stack<IPropertyTree>();
stack.Push(self);
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in current.ChildNodes)
{
stack.Push(child);
}
}
}
}
This should allow each property to have a unique key, and keep the key and property value tightly coupled. It should also allow you to move the save/update logic to a centralized place.
Of course you can implement a concrete class of IPerson for each type and hard code the individual implementations.
Since you know the person type the moment you are creating an instance of PersonVMM, you could add an attribute PersonTypeId and set it from the constructor,
void SomeMethod()
{
var personVm = new PersonVM(WordUtils.OwnerName);
}
class PersonVM : INotifyPropertyChanged
{
// properties
string PersonTypeId { get; set; }
string Name { get; set; }
string PhoneNumber { get; set; }
public PersonVM()
{}
public PersonVM(string personTypeId)
{
PersonTypeId = personTypeId;
}
// methods to get data or save data of this properties to or from the word document
void saveMyPropertyValuesToWord()
{
Name = MyApp.MyWordDocument.GetCustomProperty(PersonTypeId);
}
}
Well from the beginning, I've got a simple generic interface:
public interface IItemContainer<T> where T : Item
{
T ChosenItem { get; set; }
}
And an class that implements it multiple times:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
public FabulousItem ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
}
I can't make the ChosenItems of types NiceItem and GreedyItem public, and also I can't access it like this:
ChosenItem<GreedyItem> = new GreedyItem();
cuz' I've got an error:
'GreedyItem' is a type, which is not valid in the current context
Is there anyway to use those props in this manner or I've got it all wrong and should do It with Dictionary or other way?
When you like to keep your generic IItemContainer you can implement a GetChosenItem and SetChosenItem method like this.
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
public T GetChosenItem<T>()
where T : Item
{
return ((IItemContainer<T>)this).ChosenItem;
}
public void SetChosenItem<T>(T value)
where T : Item
{
((IItemContainer<T>)this).ChosenItem = value;
}
}
Which comes very close to what you were trying to do.
container.SetChosenItem<NiceItem>(new NiceItem());
Yours is a case explicit interface implementations were made for. You give your conflicting items a unique name and forward the items to the interface. That also avoids any naming confusions:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem> {
public FabulousItem ChosenFabulousItem { get; set; }
public NiceItem ChosenNiceItem { get; set; }
public GreedyItem ChosenGreedyItem { get; set; }
FabulousItem IItemContainer<FabulousItem>.ChosenItem {
get {
return ChosenFabulousItem;
}
set {
ChosenFabulousItem = value;
}
}
NiceItem IItemContainer<NiceItem>.ChosenItem {
get {
return ChosenNiceItem;
}
set {
ChosenNiceItem = value;
}
}
GreedyItem IItemContainer<GreedyItem>.ChosenItem {
get {
return ChosenGreedyItem;
}
set {
ChosenGreedyItem = value;
}
}
}
Assignment is simple:
container.ChosenFabulousItem = new FabulousItem();
container.ChosenNiceItem = new NiceItem();
container.ChosenGreedyItem = new GreedyItem();
If you have more complex conversion logic in the background (e.g. you assign a FaboulousItem and need to convert it into a NiceItem), you can do so by providing getters and/or setters for your public properties.
It's completely wrong. As you should know you cannot make same names for member items (properties, fields etc. ). It will confuse compiler.
I would suggest to modify your interface a bit like :
public interface IItemContainer
{
List<Item> ChosenItems { get; set; }
T ChosenItem<T>() where T : Item;
}
Now in your implementation :
public class ItemContainer : IItemContainer
{
IItemContainer.ChosenItems
{
get { // your implementation
}
set { // your implementation
}
}
T IItemContainer.ChosenItem<T>()
{
return ((IItemContainer)this).ChosenItems.OfType<T>().FirstOrDefault();
}
}
This method will let you store different objects that derive from Item and return desired one using ChosenItem<T>() method.
EDIT:
I've got another interface which operates on List of Items, cuz' some submodules works only on one Item, and some only on set. I need also to store an instance of each implemented type independently.
You can always use something like a factory collection ( dont know if the name is correct ).
public class ChosenItemCollection
{
Dictionary<Type, Item> _fac = new Dictionary<Type, Item>();
public T Add<T>(T item) where T : Item
{
if(!_fac.ContainsKey(typeof(T))
{
_fac.Add(typeof(T), item);
}
else
{
_fac[typeof(T)] = item;
}
}
public T GetChosenItem<T>() where T : Item
{
if(_fac.ContainsKey(typeof(T))
return _fac[typeof(T)];
return null;
}
}
Then in your interface instead of List<Item> ChosenItems you can do ChosenItemCollection ChosenItems.
Using this in your example :
GreedyItem item = // ...
ItemContainer.ChosenItems.Add(item);
ItemContainer.ChosenItem.ChosenItem<GreedyItem>();
I think Pidon has a nice solution. But could result in a runtime error when using not implemented Item derives.
Another solution could be adding properties which will do the casts to the implemented types:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
// these properties are only visible when casting to the correct
// interface. Which the public properties below will do.
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
// return this as IItemContainer<FabulousItem>
public IItemContainer<FabulousItem> AsFabulous
{
get
{
return (IItemContainer<FabulousItem>)this;
}
}
// return this as IItemContainer<NiceItem>
public IItemContainer<NiceItem> AsNice
{
get
{
return (IItemContainer<NiceItem>)this;
}
}
// return this as IItemContainer<GreedyItem>
public IItemContainer<GreedyItem> AsGreedy
{
get
{
return (IItemContainer<GreedyItem>)this;
}
}
}
ChosenItemsContainer container = new ChosenItemsContainer();
container.AsFabulous.ChosenItem = new FabulousItem();
container.AsNice.ChosenItem = new NiceItem();
container.AsGreedy.ChosenItem = new GreedyItem();
This way each implemented type has it's own ChosenItem instance. I think this is a clean solution without cluttering of generic <T> in code.
I have this class
public class SPP {
static PPModel PP= null;
public PPModel sPP
{
set
{
if (PP != value)
{
PP = value;
//save PP in database
}
}
get
{
if (PP == null)
{
//lazy loading of PP
}
return PP;
}
}
}
public class PPModel
{
public string property1 { get; set; }
public int property2 { get; set; }
public int property3 { get; set; }
public int property4 { get; set; }
public Dictionary<string, int> property5 { get; set; }
}
Now if I set sPP in this way, everything works fine:
SSP.Instance.sPP = new PPModel(){...};
But I want to know if it is possible to just update one property of this singleton and trigger the setter in this way:
SSP.Instance.sPP.property4 = 7;
If I do it in this way, the singleton sPP has the updated value, but the setter seems not to be triggered what means the additional code like database save will not work.
Any chances to get this working?
Thanks in advance.
a good solution for this is to change the model to have full properties definitions, and on the setters, call the DB update, as such:
public class PPModel
{
private string _fieldOne;
public string Property1
{
get { return _fieldOne; }
set
{
_fieldOne = value;
// update DB
}
}
private int _field2;
public int Property2
{
get { return _field2; }
set
{
_field2 = value;
// update DB
}
}
// and so on for all properties
}
You can't trigger setter in your singleton by updating internal stored object properties.
You can trigger your setter like this:
SSP.Instance.sPP = new PPModel(){...};
var instance = SSP.Instance.sPP;
instance.property4 = 7
SSP.Instance = instance;
This way you'll reset the exact variable to your instance and trigger update.
But, as you're implementing singleton, it is NOT responsible for making actions related to the object it stores.
You have to monitor changes in your PPModel object, as only this class is responsible for it's internal state.
I have to classes, Father and Child (by example)
A snippet of my implementation
Class Father.cs
public class Father
{
public int Id { get; set; }
public string Name { get; set; }
public List<Child> Children { get; set; }
public Father()
{
}
}
Class Child.cs
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public Child()
{
}
}
I'am trying to do something like this
Father f = new Father();
f.Children[0]; // ok
f.Children[1]; // ok
f.Children["John"]; // Duh!
I now, its wrong, i need to implement something in Child Class, i tryed this
public Child this[string name]
{
get
{
return this;
}
}
But this doesnt work.
How can i implement this feature for my class Child?
A List<T> doesn't have a string indexer; you could add one to the Father class, but the usage will be:
var child = parent["Fred"];
(no .Children)
For the indexer itself: Try (in the indexer):
return Children.FirstOrDefault(c=>c.Name==name);
To get an indexer on the list itself, you would have to create a custom list type and add the indexer there.
IMO, a method may be clearer (on Father):
public Child GetChildByName(string name) {...}
Or you can set it up like this:
public class Father
{
public int Id { get; set; }
public string Name { get; set; }
public Children Children { get; set; }
public Father()
{
}
}
public class Children : List<Child>
{
public Child this[string name]
{
get
{
return this.FirstOrDefault(tTemp => tTemp.Name == name);
}
}
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public Child()
{
}
}
Then you call it how you want.
In father class, you could write following code:
public Child this[string name]
{
get
{
return Children.Where(c => c.Name == name);
}
}
and use it like:
Father f = new Father();
f.Children[0]; // ok
f.Children[1]; // ok
f["John"]; // ok!
You are treating the List of Children like a Dictionary (Dictionaries can be accessed by key). Just change your List to a Dictionary and set the string to be the Child's name.
You could make the Children List into an OrderedDictionary so that you can reference it by index or key and then add the objects with the name as the key. Just so you know though, any of these options can run into issues if you have multiple children with the same name.