Унаследованный класс C # теряет «эталон» - PullRequest
5 голосов
/ 25 октября 2010

У меня есть частичный класс, использующий интерфейс, потому что я не могу унаследовать исходный абстрактный класс из-за того, что другой частичный класс автоматически генерируется из Entity Framework 4 и, следовательно, уже наследует ObjectContext.

Iу меня есть следующее для моего частичного класса:

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.

Как я могу сделать так, чтобы наследующий класс был правильно идентифицирован?

Вот вызывающая консольclass:

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!Я так близко, это довольно неприятно.

Ричард

1 Ответ

2 голосов
/ 25 октября 2010

Я полагаю, что ваша реализация 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);
    }
}

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

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