Take the following example code:
public abstract class ElementBase
{
}
public class ElementOne : ElementBase
{
}
public class ElementTwo : ElementBase
{
[XmlElement("element-one", typeof(ElementOne))]
[XmlElement("element-two", typeof(ElementTwo))]
public ElementBase[] SubElements { get; set; }
}
[XmlRoot("root-element")]
public class RootElement
{
[XmlElement("element-one", typeof(ElementOne))]
[XmlElement("element-two", typeof(ElementTwo))]
public ElementBase[] SubElements { get; set;}
}
The attributes on ElementOne.SubElements and ElementTwo.SubElements need to stay in sync (i.e., attributes added to one will need to be added to the other, and arguments need to stay the same), The reason for this is that in the xml, <element-one> and elements can both appear as subelements to <root-element> and <element-two>. The elements can be in any order, and the order is important. Also, there will probably be more subelements in the future. The way it is currently coded will make maintenance tedious and error-prone because of the need to maintain two separate places for attributes.
Is there a way to have these attributes "shared" between the two properties, such that a single edit will affect them both? I tried the following:
public class CommomAttribute : Attribute
{
public XmlElementAttribute f = new XmlElementAttribute("element-one", typeof(ElementOne));
public XmlElementAttribute l = new XmlElementAttribute("element-two", typeof(ElementTwo));
}
I then replaced the redundant attributes on the above classes' properties with a single [Command]. This didn't work.
An alternative question: is there a more elegant way to solve this problem?
You can try this if you don't mind having to go one level deeper to get to you sub-element items:
public abstract class ElementBase
{
}
public class ElementOne : ElementBase
{
}
public class ElementTwo : ElementBase
{
public SubElementList SubElements { get; set; }
}
public class SubElementList
{
[XmlElement("element-one", typeof(ElementOne))]
[XmlElement("element-two", typeof(ElementTwo))]
public ElementBase[] Items { get; set; }
}
[XmlRoot("root-element")]
public class RootElement
{
public SubElementList SubElements { get; set; }
}
Off the top of my head, I'd do the following:
On the ctor of each class (One and Two), require and instance of ElementBase and keep it as a private attribute (let's say, "SyncingElement")
Modify the setter of SubElements, to sync with the instance of "SyncingElement"
This way, SubElements on both objects would have the same memory address (same instance). So, if someone get the instance of SubElements from One modifies the object at index [2] (for example), it would affect SubElements at Two as well.
Related
I am thinking about the best practice in OOP for the following problem:
We have a program that is working with an external API.
The API has an object of type Element which is basically a geometric element.
Our application is a validation application that runs on a geometric model
The application takes a collection of those elements and performs some geometric tests on them.
We wrap this API element with our own class called "ValidationElement" and save some additional information to this wrapper element that can not be obtained directly from the API Element but is required by our application.
So far so good, but now the application should expand and support other types of models (basically we can say that the app is running in a different environment).
Specifically for this environment (and it does not apply to the previous cases), we want to save an additional parameter that obtaining it results in low performance.
What is the best practice option to implement it?
On one hand, I would like to avoid adding extra parameters that are not relevant to a specific(the first) part of the program.
And on the second hand, I am not sure that I want to use inheritance and split this object just for this small additional property.
public class ValidationElement
{
public Element Element { get; set; }
public XYZ Location {get; set;}//The extra property
}
The first and easy option is that the same class will have the additional property and calculation method:
public class ValidationElement
{
public Element Element { get; set; }
public XYZ Location {get; set;}//The extra property
public string AdditionalProperty { get; set; }
public void HardProcessingCalcOfAdditionalProperty()
{
//hard processing
AdditionalProperty = result
}
}
The second option that I mentioned is the inheritance
public class SecondTypeValidationElement : ValidationElement
{
public string AdditionalProperty { get; set; }
public void HardProcessingCalcOfAdditionalProperty()
{
//hard processing
AdditionalProperty = result
}
}
What do you think is the best practice for this? Is there any other way or design pattern that should help me achieve the goal?
I would like to avoid adding extra parameters that are not relevant to a specific(the first) part of the program.
It looks like it is a sign that an inheritance shoulbe be avoided here. As there is a strong possibility that this behaviour is not applicable for other classes.
And this is the second reason to avoid of creation some abstraction:
Element which is basically a geometric element
Because:
all derived elements will have these additional properties.
there are many articles which show how Liskov substitution principle can be violated in geometry figures
So let's prefer composition over inheritance.
So, in my view, it would be really good if we move all heavy, tightly coupled logic of calculating of additional property to separate class:
public class ValidationElement
{
public string Element { get; set; }
public SomeExtra AdditionalProperty { get; set; }
}
public class SomeExtra
{
public string Location { get; set; }//The extra property
public string AdditionalProperty { get; set; }
public void HardProcessingCalcOfAdditionalProperty()
{
//hard processing
AdditionalProperty = string.Empty;
}
}
Why have we created separate class SomeExtra and put logic here:
if we want to edit logic HardProcessingCalcOfAdditionalProperty, then we will edit just one class SomeExtra. By doing this we are satisfying Single Responsibility Principle of SOLID principles.
we can easily create some base abstract class for SomeExtra and then at runtime we can decide what concrete implementation should be injected. By doing this we are satisfying Open Closed Principle of SOLID principles.
UPDATE:
I really like this answer about whether inheritance or composition should be chosen:
My acid test for the above is:
Does TypeB want to expose the complete interface (all public methods no less) of TypeA such that TypeB can be used where TypeA is
expected? Indicates Inheritance.
e.g. A Cessna biplane will expose the complete interface of an airplane, if not more. So that makes it fit to derive from Airplane.
Does TypeB want only some/part of the behavior exposed by TypeA? Indicates need for Composition.
e.g. A Bird may need only the fly behavior of an Airplane. In this case, it makes sense to extract it out as an interface / class /
both and make it a member of both classes.
Update: Just came back to my answer and it seems now that it is incomplete without a specific mention of Barbara Liskov's Liskov
Substitution Principle as a test for 'Should I be inheriting from
this type?'
OOP and SOLID best practice is to use abstractions (interfaces or abstract classes), wich is closer to your second approach.
Dependency Inversion Principle:
The Dependency Inversion principle
states that our classes should depend upon interfaces or abstract
classes instead of concrete classes and functions.
Your first approach to edit the ValidationElement class is generally a bad idea, given that there are several environments for the project to be run onto.
In addition, maintaining and developing the project on this approach is not scalable and will be a headache in the long run.
Open-Closed Principle: The Open-Closed Principle requires that classes should be open for extension and closed to modification.
I suggest below designing:
public interface IValidationElement
{
Element Element { get; set; }
XYZ Location {get; set;}//The extra property
// declare other base properties and methods
}
public class ValidationElement: IValidationElement
{
public Element Element { get; set; }
public XYZ Location {get; set;}//The extra property
// define other base properties and methods
}
public interface ISecondTypeValidationElement: IValidationElement
{
string AdditionalProperty { get; set; }
void HardProcessingCalcOfAdditionalProperty();
}
public class SecondTypeValidationElement: ISecondTypeValidationElement
{
public string AdditionalProperty { get; set; }
public void HardProcessingCalcOfAdditionalProperty()
{
//hard processing
AdditionalProperty = result
}
}
public interface IThirdEnvironmentValidationElement: IValidationElement
{
string ThirdProperty { get; set; }
void RequiredProcessing();
}
public class ThirdEnvironmentValidationElement: IThirdEnvironmentValidationElement
{
public string ThirdProperty { get; set; }
public void RequiredProcessing()
{
//related operations
}
}
I am not going to repeat Open-close, DI, or other principals. It is already discussed. I would look at something like this, or even alternatively use Extensions to setup the value.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// old updated
public class Element
{
public Element(string msg) { Message = msg; }
public string Message;
}
public class XYZ { }
public class ABC { }
// new
public interface IDoesSomething
{
void SetResult();
}
// create 2 different wrappers
public class ValidationElementWrapper : IDoesSomething
{
public ValidationElementWrapper(Element el)
{
Element = el;
}
public Element Element { get; private set; }
public XYZ Location {get; set;}
public void SetResult()
{
Console.WriteLine("This is " + Element.Message);
// Do nothing
}
}
public class ValidationElementWrapper2 : IDoesSomething
{
public ValidationElementWrapper2(Element el)
{
Element = el;
}
public Element Element { get; private set; }
public XYZ Location {get; set;}
public string AdditionalProperty { get; set; }
public void SetResult()
{
AdditionalProperty = "Set additional property on wrapper 2";
Console.WriteLine("This is " + Element.Message + " and it has additional property - " + AdditionalProperty);
}
}
// run your program
public class Program
{
public static void Main()
{
var list = new List<IDoesSomething>();
list.Add(new ValidationElementWrapper(new Element("Element 1")));
list.Add(new ValidationElementWrapper2(new Element("Element 2")));
list.ForEach(item => item.SetResult());
}
}
Output
This is Element 1
This is Element 2 and it has additional property - Set additional property on wrapper 2
Alternatively, you can start with more basic class and then keep extending it
public class ValidationElementWrapper : IDoesSomething
{
public ValidationElementWrapper(Element el)
{
Element = el;
}
public Element Element { get; private set; }
public XYZ Location {get; set;}
public virtual void SetResult() // <--- virtual
{
// Do nothing
Console.WriteLine("This is " + Element.Message);
}
}
public class ValidationElementWrapper2 : ValidationElementWrapper // <-- inheritnce
{
public ValidationElementWrapper2(Element el) : base(el)
{
}
public XYZ Location {get; set;}
public string AdditionalProperty { get; set; }
public override void SetResult() // <--- override
{
AdditionalProperty = "Set additional property on wrapper 2";
Console.WriteLine("This is " + Element.Message + " and it has additional property - " + AdditionalProperty);
}
}
Result will be the same
I have a parent class that I want to have many flat children. That means 10 or more different classes would inherent from one class.
Here is what I have.
Base Class:
[ProtoContract]
[ProtoInclude(500, typeof(Message1Send))]
[ProtoInclude(501, typeof(Message2Send))]
public class MessageBase
{
[ProtoMember(1)]
public string Topic {get;set;}
[ProtoMember(2)]
public string Action { get; set; }
}
2 of many Child Classes:
[ProtoContract]
public class Message1Send : MessageBase
{
[ProtoMember(1)]
public string Property1 { get; set; }
}
[ProtoContract]
public class Message2Send : MessageBase
{
[ProtoMember(1)]
public string Property1 { get; set; }
}
I want to be able to tell the child object I am part of a base class.
I don’t what to get to the point where my base class is as follows:
[ProtoContract]
[ProtoInclude(500, typeof(Message1Send))]
[ProtoInclude(501, typeof(Message2Send))]
[ProtoInclude(502, typeof(Message3Send))]
[ProtoInclude(503, typeof(Message4Send))]
[ProtoInclude(504, typeof(Message5Send))]
[ProtoInclude(505, typeof(Message6Send))]
[ProtoInclude(506, typeof(Message7Send))]
[ProtoInclude(507, typeof(Message8Send))]
[ProtoInclude(508, typeof(Message9Send))]
[ProtoInclude(509, typeof(Message10Send))]
public class MessageBase
{
[ProtoMember(1)]
public string Topic {get;set;}
[ProtoMember(2)]
public string Action { get; set; }
}
Is there a way I can have each one of the Send classes to just add one reference to the base class so I don’t have to keep adding ProtoInclude for every flat child I create?
The problem is one of reliability. Reflection makes veryfew repeatable / reliable guarantees, and it is very important that if you serialize data today, then edit your app to add two new types, each type still has the same number as it did oroginally. Even if you've added some new types, renamed some, and possibly removed two that you weren't really using.
The attribute guarantees this by making the field-number repeatable. The reason it is on the parent (not the child) is that it is much more reliable to walk up the type-chain than down it.
However: if you have a reliable repeatable way of generating field numbers for sub-types, you can use RuntimeTypeModel to configure the serializer to your liking.
I have the following problem:
public interface IControlSingleContainer
{
ControlCollection Content { get; set; }
}
public interface IControlCollectionContainer
{
// I need to obtain a List of objects that implement IControlSingleContainer interface
List<IControlSingleContainer> Items { get; set; }
}
public class TabItem : IControlSingleContainer
{
public ControlCollection Content { get; set; }
}
public class TabbedContainer : IControlCollectionContainer
{
public List<TabItem> Items { get; set; } <- ERROR!
}
This code expect a List<IControlSingleContainer> in the property TabbedContainer.Items but I try to create classes with Items property that contains objects that implement IControlSingleContainer.
EDITED: Basically, the compilation error is the following:
'Cosmo.UI.Controls.TabbedContainer' does not implement interface member 'Cosmo.UI.Controls.IControlCollectionContainer.Items'. 'Cosmo.UI.Controls.TabbedContainer.Items' can not implement' Cosmo.UI.Controls.IControlCollectionContainer.Items' because it has the kind of matching return value of 'System.Collections.Generic.List <Cosmo.UI.Controls. IControlSingleContainer>'.
I explored a solution with generic interfaces but without any results...
Not entirely sure what you are trying to do here but you can't coerce a List<interface> into a List<concrete>. However, you can make your interface generic and add a constraint like this:
public interface IControlCollectionContainer<T> where T : IControlSingleContainer
{
List<T> Items { get; set; }
}
Now your class definition becomes this:
public class TabbedContainer : IControlCollectionContainer<TabItem>
{
public List<TabItem> Items { get; set; }
}
You're close,
public class TabbedContainer : IControlCollectionContainer
{
public TabbedContainer()
{
Items = new List<IControlSingleContainer>();
var t = new TabItem();
Items.Add(t);
}
public List<IControlSingleContainer> Items { get; set; }
}
This is one of the reasons explicit interface implementations exist depending on your use-case.
In your situation, you want your Items to be TabItem when working with that TabbedContainer directly. However, the interface requires Items to be a specific interface.
The trick is to declare TabbedContainer.Items and also IControlCollectionContainer at the same time, but reusing your TabItem class behind the scenes.
public class TabbedContainer : IControlCollectionContainer
{
public List<TabItem> Items { get; set; }
List<IControlSingleContainer> IControlCollectionContainer.Items
{
get
{
return // Your actual tab items
}
set
{
Items = //Whatever you need to do make sure you have actual
// TabItem objects
}
}
}
You'll need to update the sample above to actually handle setting/getting of interface's version of the items, but the main idea is to reuse your TabItem collection so they are always in sync.
What this actually does is when you are working with TabbedContainer and call Items, you will get a list of TabItem, but when working with your instance as an IControlCollectionContainer, your Items will return you the IControlCollectionContainer.Items instead.
Do note though that this can become quite a complex venture depending on how you are passing/modifying the instance of the container. It can be tricky to try and get these to sync if you are constantly modifying the items through TabbedContainer and IControlCollectionContainer declarations. Doing explicit implementations can sometimes help you take a step back and re-evaluate exactly what it is your end goal is and what types you declare on your properties.
For instance, if you aren't actually adding items to your interface's list, then why even use List? It could be better as an IEnumerable<T> or IReadOnlyCollection<T>.
I just try to redesign my Silverlight-4 App and tried a bit around with generics.
Simply speaking, I have a tree which can contain 2 types of nodes. As a base class, I created a class that does all the "organization", like having a list of children, a parent, a method to add a child and so on:
public abstract class BaseNode<T> : INotifyPropertyChanged where T: BaseNode<T>
{
protected ObservableCollection<T> _children;
...
}
Second, I add a class that inherits from BaseNode and is the basis for all my treenodes:
public class ServiceNodeBase<T> : BaseNode<ServiceNodeBase<T>> where T : ServiceNodeBase<T>
{
public string Description { get; set; }
...
}
And finally, as I can have two different kinds of nodes, I create a class for each kind, i.e.:
public class ServiceNodeComponent<T> : ServiceNodeBase<ServiceNodeComponent<T>> where T : ServiceNodeComponent<T>
{
public HashSet<Attributes> Attributes { get; set; }
...
}
In the ServiceNodeComponent, I need a method, that scans the tree i.e. to get all the child nodes, that are of the Type ServiceNodeComponent. When parsing the tree, I need to use the parent-type of ServiceNodeComponent (ServiceNodeBase), because the child nodes can also be of the other type.
Now, I do not know how to instantiate the ServiceNodeBase-Variable.
public HashSet<ServiceNodeComponent<T>> GetAllChildComponents()
{
// declaring the container for the found Components is no problem
HashSet<ServiceNodeComponent<T>> resultList = new HashSet<ServiceNodeComponent<T>>();
// but now: how to declare the container for the ServiceBaseNodes?
HashSet<ServiceNodeBase<???>> workingList = new HashSet<ServiceNodeBase<???>>();
Any ideas, how I would implement this?
Thanks in advance,
Frank
The problem is the constraint. It would work if you change it to
public class ServiceNodeComponent<T> : ServiceNodeBase<ServiceNodeComponent<T>>
where T : ServiceNodeBase<T> {
public HashSet<ServiceNodeComponent<T>> GetAllChildComponents() {
// ...
HashSet<ServiceNodeBase<T>> workingList = new HashSet<ServiceNodeBase<T>>();
// ...
}
}
I have 2 derived classes that will be serialized into xml.
While the code works fine (XmlSerializer, nothing strange), the serialization of DataScenario causes its MyData property items to produce Xmlelement names from the base class name:
<DataScenario>
<MyData>
<ScenarioData/>
<ScenarioData/>
<ScenarioData/>
</MyData>
<DataScenario>
Instead, i'm trying to have these items produce XmlElement names from their derived classes
<DataScenario>
<MyData>
<type1/>
<type1/>
<type2/>
</MyData>
<DataScenario>
Is this even possible? Keep in mind I need to deserialize as well; I'm unsure whether the Deserialize process will understand that derived objects need to be created.
Sample code i'm using is as follows.
[Serializable]
[XmlInclude(typeof(Type1))]
[XmlInclude(typeof(Type2))]
public class Scenario
{
[XmlElement("location")]
public string Location { get; set; }
[XmlElement("value")]
public string Value { get; set; }
public Scenario()
{
}
}
[Serializable]
[XmlType("type1")]
public class Type1 : Scenario
{
public FillPointData() : base() { }
}
[Serializable]
[XmlType("type2")]
public class Type2 : Scenario
{
public TestData() : base() { }
}
//Hosting class of all scenarios
public DataScenario()
{
public List<Scenario> MyData{ get; set; }
}
You can define what kind of Elements are in the Collection with the XmlArrayItem attribute.
If the Type is known (defined as you did with the XmlInclude attribute) it will create Tags "Type1", "Type2". If the Types are not known, it will still create a Tag called ScenarioData with an Attribute xsi:type="Type1" which is used to map the type while deserialization.
[XmlArrayItem(typeof(Type1))]
[XmlArrayItem(typeof(Type2))]
Public List<Scenario> Children
{
// getter & setter
}