2010-10-25 5 views
5

У меня есть частичный класс с использованием интерфейса, потому что я не могу наследовать то, что было оригинальным абстрактным классом из-за того, что другой частичный класс был автоматически сгенерирован из Entity Framework 4 и поэтому уже наследует ObjectContext.Inherited C# Class Losing "Reference"

У меня есть следующие для моего разделяемого класса:

namespace Model 
{ 
    using Microsoft.Practices.EnterpriseLibrary.Validation; 
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators; 
    using Utilities.BusinessRules; 
    using Utilities.BusinessRules.Rules; 

    [HasSelfValidation] 
    public partial class MyObject : IBusinessObject 
    { 
     private readonly IBusinessObject businessObject = new BusinessObject(); 

     private IBusinessObject BusinessObject 
     { 
      get 
      { 
       return businessObject; 
      } 
     } 

     public Comment() 
     { 
      AddRule(new ValidateRequired("Title")); 
     } 

     public void AddRule(BusinessRule rule) 
     { 
      BusinessObject.AddRule(rule); 
     } 

     [SelfValidation] 
     public void Validate(ValidationResults results) 
     { 
      BusinessObject.Validate(results); 
     } 
    } 
} 

Вот интерфейс:

namespace Utilities.BusinessRules 
{ 
    using Microsoft.Practices.EnterpriseLibrary.Validation; 

    public interface IBusinessObject 
    { 
     void AddRule(BusinessRule rule); 

     void Validate(ValidationResults results); 
    } 
} 

И реализация:

namespace Utilities.BusinessRules 
{ 
    using System.Collections.Generic; 
    using System.Linq; 
    using Microsoft.Practices.EnterpriseLibrary.Validation; 
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators; 

    public class BusinessObject : IBusinessObject 
    { 
     private readonly IList<BusinessRule> businessRules = new List<BusinessRule>(); 

     public void AddRule(BusinessRule rule) 
     { 
      this.businessRules.Add(rule); 
     } 

     [SelfValidation] 
     public void Validate(ValidationResults results) 
     { 
      foreach (var rule in this.businessRules) 
      { 
       if (!rule.Validate(this)) 
       { 
        results.AddResult(new ValidationResult(rule.ErrorMessage, this, rule.Key, rule.Tag, null)); 
       } 
      } 
     } 
    } 
} 

Не беспокойтесь о правилах, они работают. Проблема в том, что если я использую абстрактный класс в тестовом проекте, метод Validate() в BusinessObject будет правильно идентифицировать (это) как любой класс, унаследованный от абстрактного класса (в этом примере я бы ожидал, что это MyObject). К сожалению, переход на интерфейс (это) теряет наследующий класс и вместо этого идентифицирует это как BusinessObject.

Как это сделать, чтобы класс наследования был правильно идентифицирован?

Вот вызова консоли класс:

namespace ModelConsumer 
{ 
    using Model; 
    using System; 
    using Microsoft.Practices.EnterpriseLibrary.Validation; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var myEntities = new MyEntities()) 
      { 
       var myObject= new MyObject(); 

       myObject.Title = "Credo"; 

       var validationResults = Validation.Validate(myObject); 

       if (validationResults.IsValid) 
       { 
        myEntities.MyObjects.AddObject(myObject); 
        //myEntities.SaveChanges(); 

        Console.WriteLine("Valid."); 
       } 
       else 
       { 
        foreach (var validationResult in validationResults) 
        { 
         Console.WriteLine(validationResult.Message); 
        } 
       } 

       Console.Read(); 
      } 
     } 
    } 
} 

Это должно быть действительным, но вместо этого будет недействительна, потому что (это) идентифицируется как тип BusinessObject вместо MyObject.

Argh! Я так близко, это довольно неприятно.

Ричард

+0

Почему 'public Comment()' не имеет типа возврата? – leppie

+0

Это конструктор, поэтому не имеет типа возврата. – Richard

ответ

2

Я считаю, что ваша реализация BusinessObject написана в предположении, что он будет наследоваться. Тем не менее, теперь, когда вы г использовать его в качестве составной объект, вам нужно сделать несколько изменений:

public interface IBusinessObjectValidator 
{ 
    void AddRule(BusinessRule rule); 

    void Validate(IBusinessObject target, ValidationResults results); 
} 


Public class BusinessObject: IBusinessObjectValidator 
{ 
... 

    public void Validate(IBusinssObject target, ValidationResults results) 
    { 
     foreach (var rule in this.businessRules) 
     { 
      if (!rule.Validate(target)) 
      { 
      results.AddResult(new ValidationResult(rule.ErrorMessage, target, rule.Key, rule.Tag, null)); 
      } 
     } 
    } 
} 

И вы будете использовать его следующим образом:

[HasSelfValidation] 
    public partial class MyObject : IBusinessObject 
    { 
     private readonly IBusinessObjectValidator validator = new BusinessObject(); 

     private IBusinessObjectValidator BusinessObjectValidator 
     { 
      get 
      { 
       return validator ; 
      } 
     } 
    public Comment() 
    { 
     AddRule(new ValidateRequired("Title")); 
    } 

    public void AddRule(BusinessRule rule) 
    { 
     validator .AddRule(rule); 
    } 

    [SelfValidation] 
    public void Validate(ValidationResults results) 
    { 
     validator.Validate(this, results); 
    } 
} 

По сути, мы говорим, что мы будем имеют реализацию валидатора извне и, следовательно, нам нужно, чтобы целевой объект (который проверяется) передавался методу проверки. Я также предлагаю переименовать BusinessObject как BusinessObjectValidtor.

+0

Привет, спасибо за ваш ответ. Думаю, это определенно направление. Но если BusinessObject переименован в BusinessObjectValidator (хорошая точка), что называется IBusinessObject/BusinessObject в вашем коде? – Richard

+0

Получил! Это второй интерфейс. С небольшой настройкой у меня теперь есть работа :) Большое спасибо. – Richard

Смежные вопросы