Шаблон проектирования C #: универсальный метод? - PullRequest
1 голос
/ 28 ноября 2009

и спасибо за любую помощь

Для:

public abstract class EntityBase
{    
 protected void Create(EntityBase c)    
 {        
    Log.Audit(c);
 }
}

public class Customer : EntityBase
{    
 public void CreateCustomer(Customer c)    
 {        
  Create(c);    
 }    
 }
}

public class Car : EntityBase
{    
 public void CreateCar(Car c)    
 {        
  Create(c);    
 }    
 }
}

Для приведенного выше примера 1) Как бы вы реализовали сигнатуру метода для: Log.Audit (с);

2) Внутри метода Audit (c) нам нужно привести c к соответствующему типу и просмотреть все свойства объекта для целей аудита. Как бы это было достигнуто. Я думаю что-то вроде ....

public Audit(T t)
{
 switch (t.GetType())
 {
 case Customer:
    //Audit Customer
    Audit(<Customer> t); 
    break;
 case Car:
    //Audit Car
    Audit(<Car> t); 
 }
}

Просто предположение, любая помощь будет отличной.

Примечание. Если вы можете придумать лучший способ создания этого метода, сообщите мне.

Еще раз спасибо. Стивен

Ответы [ 3 ]

5 голосов
/ 28 ноября 2009

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

Одним из решений было бы сделать Audit () виртуальным методом EntityBase и заставить Audit вызывать его в экземплярах (поэтому вы переопределяете Audit в Customer или Car)

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

public abstract class EntityBase
{    
     protected void Create(EntityBase c)    
     {        
       Audit(c);
     }

     public virtual void Audit()
    {
    //Default audit code here, using reflection for instance
    }     
}

public class Car : EntityBase
{
    //Does not override, uses default Audit Code
}

public class Hamster : EntityBase
{
    public override void Audit()
    {
        //Specific code here..
    }
}

Если вы не хотите, чтобы ответственность за Аудит находилась внутри класса Entity или одного из его наследников, вам придется пойти по пути отражения.

3 голосов
/ 28 ноября 2009

Я почти всегда использую рефлексию при проведении одитинга. Если у вас есть свойства, которые имеют атрибуты (скажем, ColumnAttribute), которые их различают, вы можете использовать атрибуты, чтобы найти те свойства, которые вы хотите проверять. Вы всегда можете создать атрибут для использования и применить его при необходимости. Однако самое простое - просто проверить открытые свойства класса.

public void Audit( T t )
{
     foreach (var property in t.GetType().GetProperties())
     {
         var value = property.GetValue(t,null);
         ...do something with property.Name and value...
     }
}

Вы можете получить представление о том, как использовать это для LINQ to SQL, по адресу http://farm -fresh-code.blogspot.com / 2009/05 / auditing-insertts-and-updates-using-linq.html .

0 голосов
/ 02 октября 2012

Я бы порекомендовал базовому классу никогда не знать ничего о классах derrived. В этом случае: если вы добавляете еще один класс с производными данными, вам также необходимо каждый раз менять базовый класс. Из-за этого предложение Янна Шварца лучше вашего подхода.

Проблемой может быть тесная связь логики Customer / Car / ... с функциональностью autdit (см. принцип единой ответственности ). Это может быть плюсом для размышления (как уже предлагалось выше, и даже если это может быть медленнее), но это может стать очень сложным, если вы хотите реализовать общий подход для всех целей. Рекомендуется делегировать проблему в отдельную часть, которую можно использовать как плагин, к которому можно присоединить аспектно-ориентированное программирование . Несколько фреймворков уже поддерживают этот подход.

Если вы хотите «перевести» проблему с коммутатором на аутсорсинг, вы можете использовать стратегический шаблон . Вы можете найти пример, который я часто использовал в c # без специального фреймворка здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...