Foothill Ответов: 1

Можете ли вы вызвать методы интерфейса?


Поэтому я строю иерархию объектной модели для упрощения операций с данными и задаюсь вопросом, есть ли лучший способ сделать это.

Для краткости этот пример сильно абстрагирован. Каждый объект модели был закодирован для выполнения своих собственных операций чтения/записи, так что код пользовательского интерфейса был чистым и простым.
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);
    }
   }
  }
 }
}

Фактические классы моделей реализуют интерфейсы, необходимые для выполнения всех операций чтения/записи в базу данных. Все, что нужно сделать форме, - это отлить и проверить.

Мне интересно, есть ли лучший способ, чем cast/test/execute для интерфейсов?

Что я уже пробовал:

Я искал способ, похожий на объект?.Invoke (method); но все, что я мог найти, - это сложный способ, который использовал отражение.

1 Ответов

Рейтинг:
2

Midi_Mick

Я верю, что as оператор внутренне выполняет приведение в блоке try/catch, который, хотя и эффективен, вероятно, не является самым эффективным. Если вы ищете лучшую эффективность, возможно, код должен следовать шаблону

if (model is IPrimaryRelatable) {
    ((IPrimaryRelatable)model).RelateToSource(sourceObject, env);
}
if (model is ISecondaryRelatable) {
    ((ISecondaryRelatable)model).CreateSecondaryRelationships(data, env);
}


Foothill

Я уже использовал этот метод раньше, но он неэффективен, чтобы бросить дважды. На самом деле большинство, но не все объекты будут реализовывать интерфейс IPrimaryRelatable.

Midi_Mick

Вы можете, конечно, использовать оператор ?. непосредственно на результате операции "as":

IPrimaryRelatable pRel = модель как IPrimaryRelatable;
прель?. RelateToSource(sourceObject, env);

Foothill

Возможно, придется это сделать. Я все еще задаюсь вопросом, есть ли лучшие синтаксические сахара для тестирования интерфейсов на null, прежде чем пытаться выполнить их методы.

Midi_Mick

Сжать его до одной строки? Не вижу ничего проще.

(модель как IPrimaryRelatable)?.RelateToSource(sourceobject свойства, ОКР);