In order to assign BobsValidator to IValidator, your you need to make your interface generic parameter into a covariant, this would allow your IValidator to point to a more specific type like IValidator.
interface IValidator<out T>
{
bool Validate(T item);
}
However, you will realize you can't compile because your interface is no longer type safe, so the compiler won't allow. So why it is no longer type safe? Imagine this:
using NUnit.Framework;
namespace GenericCollectionTest
{
[TestFixture]
public class GenericCollectionTest
{
//.NET Compiling Error:
//"Invalid variance: The type parameter 'T' must be contravariantly valid ..."
interface IValidator<out T>
{
//Error: "Parameter must be type-safe. Invalid variance..."
bool Validate(T item);
}
class MyObject
{
public int TestValue { get; set; }
}
class YourObject
{
public int CheckValue { get; set; }
}
class MyValidator : IValidator<MyObject>
{
public bool Validate(MyObject item)
{
return (item).TestValue == 1;
}
}
class YoursValdator : IValidator<YourObject>
{
public bool Validate(YourObject item)
{
return (item).CheckValue == 1;
}
}
[Test]
public void Test_That_Validator_Is_Working()
{
//.NET compiler tries to prevent the following scenario:
IValidator<object> someObjectValidator = new MyValidator();
someObjectValidator.Validate(new YourObject()); // Can't use MyValidator to validate Yourobject
someObjectValidator = new YoursValdator();
someObjectValidator.Validate(new MyObject()); // Can't use YoursValidator to validate MyObject
}
}
}
To work around this, I suggest you try using non-generic as a base class so that you can store your validator in a dictionary. See if the following works for your case:
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace GenericCollectionTest
{
[TestFixture]
public class GenericCollectionTest
{
interface IValiadtor
{
bool Validate(object item);
}
abstract class ValidatorBase<T> : IValidator<T>
{
public bool Validate(object item)
{
return Validate((T)item);
}
public abstract bool Validate(T item);
}
interface IValidator<T> : IValiadtor
{
//Error: "Parameter must be type-safe. Invalid variance..."
bool Validate(T item);
}
class MyObject
{
public int TestValue { get; set; }
}
class YourObject
{
public int CheckValue { get; set; }
}
class MyValidator : ValidatorBase<MyObject>
{
public override bool Validate(MyObject item)
{
return (item).TestValue == 1;
}
}
class YoursValdator : ValidatorBase<YourObject>
{
public override bool Validate(YourObject item)
{
return (item).CheckValue == 1;
}
}
[Test]
public void Test_That_Validator_Is_Working()
{
Dictionary<Type, IValiadtor> Validators = new Dictionary<Type, IValiadtor>();
Validators.Add(typeof(MyObject), new MyValidator() );
Validators.Add(typeof(YourObject), new YoursValdator());
var someObject = new MyObject();
someObject.TestValue = 1;
Assert.That(Validators[someObject.GetType()].Validate(someObject));
}
}
}