I use Unity and want to allow all implementations that have a common type assigned from a specific type.
I am currently registering such entries:
container.RegisterType<IQueryGenerator<IPerson>, PersonQueryGenerator>("1");
container.RegisterType<IQueryGenerator<ICustomer>, CustomerQueryGenerator>("2");
container.RegisterType<IQueryGenerator<IEmployee>, EmployeeQueryGenerator>("3");
container.RegisterType<IQueryGenerator<IManager>, ManagerQueryGenerator>("4");
Then the hierarchy will look like this:
public interface IPerson
{
}
public interface ICustomer : IPerson
{
}
public interface IEmployee : IPerson
{
}
public interface IManager : IEmployee
{
}
And the implementation interface I'm trying to solve:
public interface IQueryGenerator<T>
{
IEnumerable<Expression<Func<T, bool>>> GenerateQueries();
}
Now I want to be able to resolve all IQueryGenerators, where the generic type is assigned to the type that I have. So I have a factory that should wrap it:
public class QueryFactory
{
private readonly IUnityContainer _container;
public QueryFactory(IUnityContainer container)
{
_container = container;
}
public IEnumerable<Expression<Func<TModel, bool>>> GenerateQueries<TModel>()
{
IQueryGenerator<TModel>[] queryGenerators = _container.ResolveAll<IQueryGenerator<TModel>>();
foreach (var queryGenerator in queryGenerators)
{
var result = queryGenerator.GenerateQueries();
}
}
}
I want to _container.ResolveAll<IQueryGenerator<IEmployee>>()return PersonQueryGenerator, EmployeeQueryGeneratorand ManagerQueryGeneratorbecause it IManageris IEmployeeand IEmployeeis IPerson.
_container.ResolveAll<IQueryGenerator<ICustomer>>()returns PersonQueryGeneratorand CustomerQueryGenerator.
IEmployeecan be dropped to IPerson, which can be processed with PersonQueryGenerator.
IQueryGenerators TModel? QueryGenerators TModel ?
EDIT:
, . , .
class Program
{
static void Main(string[] args)
{
IEnumerable<IManager> managers = new List<IManager>
{
new Manager()
{
Birthday = DateTime.Now.AddDays(1),
Name = "Executive Manager",
EmployeeNumber = 9,
IsExecutive = true,
Salary = 1000
},
new Manager()
{
Birthday = DateTime.Now.AddDays(-1),
Name = "Ordinary Manager",
EmployeeNumber = 8,
IsExecutive = false,
Salary = 900
},
};
var queries = GenerateQueries();
managers = queries.Aggregate(managers, (current, expression) => current.Where(expression));
foreach (var manager in managers)
{
Console.WriteLine("Manager: {0}", manager.Name);
}
Console.ReadKey();
}
static IEnumerable<Func<IManager, bool>> GenerateQueries()
{
IList<IQueryGenerator<IManager>> queryGenerators = new List<IQueryGenerator<IManager>>();
if (typeof(IPerson).IsAssignableFrom(typeof(IManager)))
{
queryGenerators.Add(new PersonQueryGenerator());
}
if (typeof(IEmployee).IsAssignableFrom(typeof(IManager)))
{
queryGenerators.Add(new EmployeeGenerator());
}
if (typeof(IManager).IsAssignableFrom(typeof(IManager)))
{
queryGenerators.Add(new ManagerQueryGenerator());
}
var queries = new List<Func<IManager, bool>>();
foreach (var queryGenerator in queryGenerators)
{
queries.AddRange(queryGenerator.GenerateQueries());
}
return queries;
}
static IEnumerable<Func<TModel, bool>> GenerateQueries<TModel>()
{
return null;
}
}
public interface IQueryGenerator<in T>
{
IEnumerable<Func<T, bool>> GenerateQueries();
}
public class ManagerQueryGenerator : IQueryGenerator<IManager>
{
public IEnumerable<Func<IManager, bool>> GenerateQueries()
{
Console.WriteLine("ManagerQueryGenerator called");
yield return x => x.IsExecutive;
}
}
public class PersonQueryGenerator : IQueryGenerator<IPerson>
{
public IEnumerable<Func<IPerson, bool>> GenerateQueries()
{
Console.WriteLine("PersonQueryGenerator called");
yield return x => x.Birthday > DateTime.Now;
}
}
public class EmployeeGenerator : IQueryGenerator<IEmployee>
{
public IEnumerable<Func<IEmployee, bool>> GenerateQueries()
{
Console.WriteLine("EmployeeGenerator called");
yield return x => x.Salary > 900;
}
}
public interface IHaveName
{
string Name { get; set; }
}
public interface IPerson : IHaveName
{
DateTime Birthday { get; set; }
}
public interface ICustomer : IPerson
{
int MoneyToSpend { get; set; }
}
public interface IEmployee : IPerson
{
int EmployeeNumber { get; set; }
int Salary { get; set; }
}
public interface IManager : IEmployee
{
bool IsExecutive { get; set; }
}
public class Manager : IManager
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
public int EmployeeNumber { get; set; }
public int Salary { get; set; }
public bool IsExecutive { get; set; }
}
:
PersonQueryGenerator called
EmployeeGenerator called
ManagerQueryGenerator called
Manager: Executive Manager
, , , Expression<Func<T,bool>>, EF.
public interface IQueryGenerator<T>
{
IEnumerable<Expression<Func<T, bool>>> GenerateQueries();
}
:
public interface IQueryGenerator<in T>
{
IEnumerable<Func<T, bool>> GenerateQueries();
}