Click here to Skip to main content
14,880,638 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
So I am building an object model hierarchy to simplify data operations and I am wondering if there is a better way to do this.

The example is highly abstracted for brevity. Each model object has been coded to perform its own read/write operations so that the UI code is clean and simple.
C#
public class DataObject
{
 // a container class that basically contains
 // information from a row in a table in the target database
}

// core interface that models implement
public interface IDataModel
{
 DataObject SourceObject { get; }
}

// interface that defines object creation function
public interface ICreatableDataModel : IDataModel
{
 // contains a single declaration with two variables, the database
 // to write to and where to get variables specific to it's environment (QA, PROD, etc...)
 DataObject CreateObject(DataAccess data, EnvironmentInfo environment);
}

// interface applied to an object that can be related to another object
public interface IPrimaryRelatable
{
 void RelateToSource(DataObject sourceObject, EnvironmentInfo environment);
}

// interface applied to objects that have secondary relationships
public interface ISecondaryRelatable
{
 void CreateSecondaryRelationships(DataAccess data, EnvironmentInfo environment);
}

// Example source data model class
public class SimpleModel : IDataModel, ICreatableDataModel
{
 public DataObject { get; set; }
 public DataObject CreateObject(DataAccess data, EnvironmentInfo environment)
 {
  // write this object to the database and return it's data representation.
 }
}

// Example related data model class
public class RelatedModel : IDataModel, ICreatableDataModel, IPrimaryRelatable, ISecondaryRelatable
{
 private List<icreatabledatamodel> _secondaryObjects;

 public DataObject { get; set; }
 public DataObject CreateObject(DataAccess data, EnvironmentInfo environment)
 {
  // write this object to the database and return it's data representation.
 }
 public void RelateToSource(DataObject source, EnvironmentInfo environment)
 {
  // this creates the relationship two objects
 }
 public void CreateSecondaryRelationships(Database database, EnvironmentInfo environment)
 {
  // this creates any secondary objects and then relates them to this object
 }
}

// In my UserControl, I wrap this up nice an neat
// There is one object that must be created on the form but there are
// several other points of data they may or may not be needed
public class MyControl : UserControl
{
 private ICreatable _primaryModel;
 private List<icreatabledatamodel> _otherModels;

 private void Create_Click(object sender, RoutedEventArgs e)
 {
  CreateObjects();
 }

 private void CreateObjects()
 {
  DataAccess data = app.Data;
  EnvironmentInfo env = app.EnvironmentInfo;
  
  // this creates the primary object 
  DataObject sourceObject = _primaryModel.CreateObject(data, env);

  // iterate through the other models that will be created from the form
  // relate them if necessary
  foreach (ICreatableDataModel model in _relatedModels)
  {
    DataObject obj = model.CreateObject(data, env);

    "The following code is what I am trying to simplify"
    // relate to source if needed
    IPrimaryRelatable pRel = model as IPrimaryRelatable;
    if (pRel != null)
    {
     pRel.RelateToSource(sourceObject, env);
    }
    // handle other relationships if needed
    ISecondaryRelatable sRel = model as ISecondaryRelatable;
    if (sRel != null)
    {
     sRel.CreateSecondaryRelationships(data, env);
    }
   }
  }
 }
}

The actual model classes implement the interfaces necessary to perform all of the read/write operations to the database. All the form needs to do is cast and test.

I am wondering, is there a better way than the cast/test/execute for interfaces?

What I have tried:

I looked for a way similar to object?.Invoke(method); but all I could find was a complicated way that used Reflection.
Posted
Updated 15-Nov-16 10:56am

1 solution

I believe the as operator internally performs a cast in a try/catch block which, although effective, is probably not the most efficient. If you're looking for better efficiency, perhaps the code should follow the pattern
C#
if (model is IPrimaryRelatable) {
    ((IPrimaryRelatable)model).RelateToSource(sourceObject, env);
}
if (model is ISecondaryRelatable) {
    ((ISecondaryRelatable)model).CreateSecondaryRelationships(data, env);
}
   
v2
Comments
Foothill 15-Nov-16 17:01pm
   
I have used that method before in the past but it is inefficient to cast twice. In reality, most, but not all, objects will implement the IPrimaryRelatable interface.
Midi_Mick 15-Nov-16 17:04pm
   
You can, of course, use the ?. operator directly on the result of the "as" operation:

IPrimaryRelatable pRel = model as IPrimaryRelatable;
pRel?.RelateToSource(sourceObject, env);
Foothill 15-Nov-16 17:17pm
   
That might have to do. I am still wondering if there is better syntactic sugars for testing interfaces for null before attempting to execute their methods.
Midi_Mick 15-Nov-16 18:10pm
   
Compress it down to one line? Can't see anything simpler.

(model as IPrimaryRelatable)?.RelateToSource(sourceObject, env);

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900