c# – Unity – 解析从T继承的泛型实现
我正在使用Unity并希望解决所有具有可从特定类型分配的泛型类型的实现.
我目前正在进行如下注册: container.RegisterType<IQueryGenerator<IPerson>,PersonQueryGenerator>("1"); container.RegisterType<IQueryGenerator<ICustomer>,CustomerQueryGenerator>("2"); container.RegisterType<IQueryGenerator<IEmployee>,EmployeeQueryGenerator>("3"); container.RegisterType<IQueryGenerator<IManager>,ManagerQueryGenerator>("4"); 层次结构如下: public interface IPerson { } public interface ICustomer : IPerson { } public interface IEmployee : IPerson { } public interface IManager : IEmployee { } 以及我正在尝试解决的实现的接口: public interface IQueryGenerator<T> { IEnumerable<Expression<Func<T,bool>>> GenerateQueries(); } 现在我希望能够解析所有IQueryGenerators,其泛型类型可分配给我的类型.所以我有一个应该包装它的工厂: public class QueryFactory { private readonly IUnityContainer _container; public QueryFactory(IUnityContainer container) { _container = container; } public IEnumerable<Expression<Func<TModel,bool>>> GenerateQueries<TModel>() { // Get all querygenerators which can handle TModel. IQueryGenerator<TModel>[] queryGenerators = _container.ResolveAll<IQueryGenerator<TModel>>(); foreach (var queryGenerator in queryGenerators) { // Do something with queryGenerator. var result = queryGenerator.GenerateQueries(); } } } 我想要的是_container.ResolveAll< IQueryGenerator< IEmployee>>()返回PersonQueryGenerator,EmployeeQueryGenerator和ManagerQueryGenerator,因为IManager是IEmployee而IEmployee是IPerson. _container.ResolveAll< IQueryGenerator< ICustomer>>()返回PersonQueryGenerator和CustomerQueryGenerator. IEmployee可以转换为IPerson,可以由PersonQueryGenerator处理. 如何注册IQueryGenerators,以及如何基于TModel解决它们?或者有没有其他方法可以根据TModel实现的接口检索QueryGenerators? 编辑: 我添加了一个我想做的概念验证.它运作良好,但非常硬编码. 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(); } // Change this to a generic method. static IEnumerable<Func<IManager,bool>> GenerateQueries() { // Change this to a more generic management 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()); } // Fetch queries and return them. var queries = new List<Func<IManager,bool>>(); foreach (var queryGenerator in queryGenerators) { // Do something with queryGenerator. queries.AddRange(queryGenerator.GenerateQueries()); } return queries; } // I want to use this method instead. static IEnumerable<Func<TModel,bool>> GenerateQueries<TModel>() { // Do the same thing as the method above //TODO: Resolve all IQueryGenerators that can handle 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(); } 解决方法
当您填充统一容器时,可能会有一点点反射.
private static UnityContainer container = new UnityContainer(); static void RegisterGenerator<T,TG>() where TG : IQueryGenerator<T> { var assembly = typeof(T).Assembly; // walk trough all interfaces in assembly,if the interface inherits from // typeof(T),add that particular IQueryGenerator<> to container as well foreach (var type in assembly.GetTypes()) { if (typeof(T).IsAssignableFrom(type) && type.IsInterface) { var generatorType = typeof(IQueryGenerator<>).MakeGenericType(type); container.RegisterType(generatorType,typeof(TG),type.Name); } } } static IEnumerable<Func<T,bool>> GenerateQueries<T>() where T : IPerson { var queryGenerators = container.ResolveAll<IQueryGenerator<T>>().ToList(); // Fetch queries and return them. var queries = new List<Func<T,bool>>(); foreach (var queryGenerator in queryGenerators) { // Do something with queryGenerator. queries.AddRange(queryGenerator.GenerateQueries()); } return queries; } 例: static void Main(string[] args) { RegisterGenerator<IPerson,PersonQueryGenerator>(); RegisterGenerator<IManager,ManagerQueryGenerator>(); var managers = new List<IPerson> { new Manager { Birthday = DateTime.Now.AddDays(1),Salary = 1000 },new Manager { Birthday = DateTime.Now.AddDays(-1),Salary = 900 } }.AsEnumerable(); var queries = GenerateQueries<IPerson>(); managers = queries.Aggregate(managers,expression) => current.Where(expression)); foreach (var manager in managers) { Console.WriteLine("Manager: {0}",manager.Name); } Console.ReadKey(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |