I have a partial class using an interface because I can’t inherit what was an original abstract class due to the other partial class being auto-generated from Entity Framework 4 and therefore already inheriting ObjectContext.
I have the following for my partial class:
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);
}
}
}
Here’s the interface:
namespace Utilities.BusinessRules
{
using Microsoft.Practices.EnterpriseLibrary.Validation;
public interface IBusinessObject
{
void AddRule(BusinessRule rule);
void Validate(ValidationResults results);
}
}
And the implementation:
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));
}
}
}
}
}
Don’t worry about the rules, they work. The problem is if I use an abstract class in a test project, the Validate() method in BusinessObject will correctly identity (this) as whatever class inherited the abstract class (in this example, I would expect that to be MyObject). Unfortunately, switching to an Interface, (this) loses the inheriting class and instead identifies this as BusinessObject.
How can I make it so the inheriting class is properly identified?
Here’s the calling console 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();
}
}
}
}
This should be valid but will instead be invalid because (this) is identified as being type BusinessObject instead of MyObject.
Argh! I'm so close, it's pretty vexing.
Richard
I believe that your implementation of BusinessObject is written assuming that it would be inherited. However, now that you r using it as a composed object, you need to make few changes:
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));
}
}
}
}
And you will use it as follows:
[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);
}
}
Essentially, we are saying that we will have an implementation of validator externally and hence, we need to have target object (that is being validated) passed to the validate method. I would also suggest to rename BusinessObject as BusinessObjectValidtor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With