Composition vs inheritance. Where did I go wrong? - c#

I need to model organizational hierarchy structure in my entities. An organization can be head-office, regional head, sub region, area office. There are a lot of common functions that the organizations are performing, but there are several functions that are specific for example only Regions can perform task A. There is also some properties(data) that is specific to Region.
I modeled it using composition and not using inheritance, but now I have ended with only a single organization class, with lot of references which depending on the TYPE of organization can have valid references or be null.
Object composition was a pain which now I am handling through factories. But now my main concern is the developers need to remember what the organization type is and whether a property has some meaning for that organization or not.
Just to be clear what I mean.
public class Organization : IKeyed<int> {
public virtual int Id { get; protected set; }
public virtual string Code { get; set; }
public virtual OrganizationType orgType {get;set;}
public virtual Organization Parent {get;set;}
public virtual IList<Organization> Children {get;set;}
public virtual typeA {get; set;} // only meaningful when organization type is 'Head office'
public virtual typeB {get;set;}// only meaningful when 'Region'
public virtual void AddChild(Organization org){...}
...
}
Should I have used inheritance over here? Or am I missing some tricks here?

In my opinion, I suggest you create an abstract base class that hold common behaviors and fields. Then you can add sub-classes to extend more specific behavior and/or properties.
public abstract class Organization : IKeyed<int> {
public virtual int Id { get; protected set; }
public virtual string Code { get; set; }
// remove this property
// public virtual OrganizationType orgType {get;set;}
public virtual Organization Parent {get;set;}
public virtual IList<Organization> Children {get;set;}
// move this property to sub-class
// public virtual typeA {get; set;} // only meaningful when organization type is 'Head office'
// move this property to sub-class
// public virtual typeB {get;set;}// only meaningful when 'Region'
public virtual void AddChild(Organization org){...}
...
}
public class HeadOffice : Organization
{
public virtual typeA { get; set; }
}
public class Region : Organization
{
public virtual typeB { get; set;}
}
public class OtherOrganizationType : Organization
{
//
}

In regards to your specific question inheritance vs. composition: The maxim i've heard over and over again is "use inheritance when object A is a type of object B. Use composition when object A is made up of object B".
In this case, you can't say that a regional office is a type of head office. Nor can you say that a head office is made up of regional offices. This tells me that the objects should not be directly related. Instead, think about what it is about each that makes them eligable to perform common tasks. Maybe they can both HireWorker because they are both HiringOrganizations, maybe they can both ReportSales because they are both SalesEntities. In these cases, you should have a HiringOrginization or SalesEntity superclass, of which both HeadOffice and RegionalOffice are subclasses.
As far as org structure goes, it might be worth considering to maintain that structure in a separate OrgStructure object. Instead of having a Parent attribute and a Child attribute in each object, your OrgStructure object would maintain the relationships between all of the object instances. This provides a bit more flexibility, and removes the responsibility of maintaining relationships into a dedicated object.

Related

How can I cast IEnumerable<DerivedClass> to IEnumerable<BaseClass> if it is a property of another class, in C# [duplicate]

As you know, C# 9.0 (.Net 5) now allows Covariant Returns. I need help applying this to a set of classes having Auto-Implemented properties.
I have two abstract classes that represent financial bank accounts and transactions. I made them abstract since I will pull data from various data sources and while the main properties will be common across all sources, each source may have additional fields I want to keep. A 1 to Many relationship exists between both classes (1 account has many transactions AND 1 transaction belongs to only 1 account).
public abstract class BankAccount
{
public string Name { get; set; }
public IList<Transaction> Transactions { get; set; } = new List<Transaction>();
...
}
public abstract class Transaction
{
public string Name { get; set; }
public virtual BankAccount BankAccount { get; set; } // This doesn't work unless I remove set;
...
}
And here is an example of the concrete implementations
public class PlaidBankAccount : BankAccount
{
public string PlaidId { get; set; }
...
}
public class PlaidTransaction : Transaction
{
public string PlaidId { get; set; }
public override PlaidBankAccount BankAccount { get; set; } // This doesn't work unless I remove set;
...
}
What I want to do is to override the base class getters and setters so that they use derived classes. For example:
If I create an instance of the concrete transaction and call the BankAccount getter, I want to get an instance of the derived PlaidBankAccount not the base BankAccount.
What I've found is that when I only define virtual getter in the base class and override it in the derived class, it works. But just as I add both properties {get;set;}, I get the same error as in previous C# versions:
error CS1715: 'PlaidTransaction.BankAccount': type must be 'BankAccount' to match overridden member 'Transaction.BankAccount'
How could I fix this?
In C# 9 properties are only able to have co-variant returns when they are readonly, so unfortunately, no set; is possible.
An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property. Beginning with C# 9.0, read-only overriding properties support covariant return types. The overridden property must be virtual, abstract, or override.
From the Microsoft Docs - Override keyword

Selectively restricting property access for specific modules

I have a class Thing that is deserialized from a JSON file using DataContractJsonSerializer:
[DataContract]
class Thing
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
// and so on...
}
To make this work, all properties need to have public or at least internal setters.
Two other modules (assemblies) need to access this class:
ThingView should have read-only access to most attributes.
ThingEditor needs full access to all attributes.
I could make the setters internal but then the ThingEditor would not get full access.
To restrict access for the ThingView class, the best idea I could come up with is to create a read-only wrapper of the Thing class. But this would involve a lot of code duplication.
Are there better ways to achieve more encapsulation for in a case like this?
(The actual code contains about 20 classes of this type, some of which form nested structures. Also, there are more than two modules that need either read or full access to the properties.)
There is nothing out of the box in the specs that would achieve this. However, you could do something like this for example
public interface IReadOnlInterface
{
int Id { get; }
string Name { get; }
}
public interface IInterface
{
int Id { get; set; }
string Name { get; set; }
}
internal class Thing : IInterface , IReadOnlInterface
{
public int Id { get; set; }
public string Name { get; set; }
}
However there is nothing stopping coders with dirty little fingers casting to the other interface. If its only a runtime issue, then interfaces should be fine. Otherwise youll have to create a better api design with secured data, and proxy type objects with readonly access, Though maybe someone has a better idea.

protobuf-net inheritance from child to parent

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.

Obtain DB Data in Polymorphism

I have base class, and multiple derived classes, like that:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Parent : Person
{
public int Age { get; set; }
}
public class Child : Person
{
public int Grade { get; set; }
public Parent Father { get; set; }
public Parent Mother { get; set; }
}
Each class has a table in the DB, with an appropirate field.
When I want to obtain data from the DB, and initalize an Person's instance, I need to set value for each property, like that:
Name = reader["Name"].ToString();
Age = int.Parse(reader["Age"].ToString());
Now, I don't want to do that on each derived class, but do that generally in the base class.
What is the best way to do that? Thank you.
First of all, the best answer you can find here is: adopt an OR/M like Entity Framework, NHibernate or Dapper (or any other) and focus your efforts in your business instead of wasting your time in infrastructure details!
In the other hand, if you want an approach to solve your issue using your own code, I would say you need to create the concept of data mapper. It would be a class which should define mapping between relational and object-oriented counterparts.
This way, when you try to obtain a derived class, you instantiate base class and derived class data mappers, and you call them to obtain the entire column data:
DerivedClass derivedClassInstance = new DerivedClass();
DerivedClassDataMapper derivedMapper = new DerivedClassDataMapper(derivedClassInstance, dataReader);
derivedMapper.Fetch();
// Now your derivedClassInstance reference will contain an object which
// has both data from base and derived class...
Finally, I would say that both data mappers should inherit from a DataMapper base class where Fetch method should be marked as virtual (or abstract) in order to let derived data mappers add more mapping code (this way, base mapper will map properties to columns defined in the base class, derived class will override Fetch to add more mappings and so on...).
Anyway, you shouldn't reinvent the wheel because there're solid object-relational mappers.

Castle DynamicProxy: create a new property with a custom attribute for XML serialization

I have a situation where I have some DTO classes that should be implemented like:
public class City
{
public string Name { get; set; }
public State State { get; set; }
}
public class State
{
public string Name { get; set; }
}
The problem is, these are actually DTO classes for REST XML resources. And the City resource may include the State resource inline, or it may simply provide the resource ID (a URI). I am handling access to the DTO via the Repository pattern and would like it to be transparent to clients whether State is lazy loaded or not (like how NHibernate does with it's entity classes).
So my current plan is to use Castle DynamicProxy to create a proxy object when the REST Repository detects that the class isn't fully "hydrated" (i.e. not everything is inline). The proxy object will know how to lazy load attributes as needed.
To actually implement this, however, the only thing I've come up with is to have backing attributes for all relationships and put the Xml attributes on those. So the strategy looks like this:
[XmlType]
public class City
{
[XmlElement]
public string Name { get; set; }
[ToOneRestRelationship(BackingPropertyName = "StateBacking")]
public State State { get; set; }
[XmlElement(Name = "state")]
public ResourceBase StateBacking { get; set; }
}
[XmlType]
public class State
{
[XmlElement]
public string Name { get; set; }
}
Then the Repository object knows to set up the proxy object to either get the object from the StateBacking property and use that (inlined resource case) or do a REST request to lazily retrieve the State object (resource URI case, i.e. lazy) from the ID specified in the backing property.
Question
The issue is, this backing field is pretty ugly. What I would like is a way to have Castle generate a class that would have the backing property with the XmlElement attribute applied that I could pass to the XmlSerializer. Then my DTO classes could look more like the first example and wouldn't have to be aware that the actual serialising class has a backing property.
Is something like this possible with Castle or any other Proxy library?
After going an interesting and completely wrong way, i think it is indeed possible to create a backing field that won't be seen by clients. Since proxying works by inheriting from the proxied class, any property on the derived class won't be seen in the scope of the original class. So mixins are the way to go:
Given Foo
public class Foo
{
public virtual string Name { get; set; }
public virtual Bar bar { get; set; }
}
and Bar
public class Bar
{
public virtual string Name { get; set; }
}
We can declare an interface that will let us retrieve the backing field and an implementation
public interface IHasBarBackingField
{
Bar RetrieveBar();
}
public class HasBarBackingField : IHasBarBackingField
{
public HasBarBackingField()
{
// the constructor must contain ways to resolve the bar. Since
// the class is built while proxying you should have all the data
// available at this moment
}
public Bar RetrieveBar()
{
return new Bar(); // example, you could have a backing field somewhere in this class
}
}
Then you just have to mixin both classes when proxying:
var pg = new ProxyGenerator();
var hasBarBackingField = new HasBarBackingField();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(hasBarBackingField);
var test = pg.CreateClassProxy<Foo>(options, new BarInterceptor());
and intercept the call interesting you in order to return the backing Bar
public class BarInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == "get_bar")
{
var hasBarBackingField = invocation.InvocationTarget as IHasBarBackingField;
invocation.ReturnValue = hasBarBackingField.RetrieveBar();
}
else
{
invocation.Proceed();
}
}
}
The HasBarBackingField class should be built to return either the direct object or retrieve the referenced REST object. Hope this helps
Based on what i've seen NSubstitute do i'd say it is possible, as long as your properties are virtual: http://nsubstitute.github.io/help/partial-subs/ .
Creating a City class with virtual property State that is then resolved at runtime using the substitution pattern should be feasable
public class City
{
public string Name { get; set; }
[StateId(10)]
public virtual State State { get; set; }
}
var sCity = Substitute.For<City>();
sCity.State.Returns((core) => {return null; // here you can access informations about the call});
Definitely doable, but it's terra incognita from here on!

Categories

Resources