2015-01-29 4 views
0

Я пытаюсь разрешить все генерические файлы, используя IEnumerable базового типа, даже не уверен, что это вообще возможно ... Я ищу решение, где Мне не нужно полагайтесь на контейнер autofac, поскольку у меня нет доступа к нему. См. Приведенный ниже код, просто скопируйте пасту в файл Program.cs, и вам понадобится ссылка на Autofac, чтобы узнать, что мне нужно :).Разрешение всех генериков как перечисляемых в Autofac

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 
using Autofac; 

namespace AutoFacExperiments 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var containerBuilder = new ContainerBuilder(); 

      //containerBuilder.RegisterGeneric(typeof (GenericManager<>)).As(typeof(IGenericManager<>)); 

      var assembly = Assembly.GetAssembly(typeof(BaseEntity)); 
      var allDerivedTypes = assembly.GetTypes().Where(t => GetBaseTypes(t).Contains(typeof(BaseEntity))); 

      var baseInterfaceType = typeof(IGenericManager<>).MakeGenericType(typeof(BaseEntity)); 
      foreach (var typeToRegister in allDerivedTypes) 
      { 
       var t = typeof(GenericManager<>).MakeGenericType(typeToRegister); 
       var interfaceType = typeof(IGenericManager<>).MakeGenericType(typeToRegister); 
       containerBuilder.RegisterType(t) 
        .As(interfaceType).As(baseInterfaceType); 

       // Autofac doesn't like .As(baseInterfaceType); 
       // if I change IGenericManager<TEntity> to IGenericManager<out TEntity> it all works but then I cannot use TEntity inside method parameters due to co/contra variance laws 
      } 

      containerBuilder.RegisterType<App>().SingleInstance(); 

      var builtContainer = containerBuilder.Build(); 
      var app = builtContainer.Resolve<App>(); 
      app.Run(); 
     } 

     private static IEnumerable<Type> GetBaseTypes(Type target) 
     { 
      do 
      { 
       yield return target.BaseType; 

       target = target.BaseType; 
      } while (target != typeof(object) && target != null); 
     } 
    } 

    internal class App 
    { 
     private readonly Func<IContext, IGenericManager<EntityOne>> _entityOneGenericManagerFactory; 
     private readonly Func<IContext, IGenericManager<EntityTwo>> _entityTwoGenericManagerFactory; 
     private readonly IEnumerable<Func<IContext, IGenericManager<BaseEntity>>> _allGenericManagerFactories; 

     public App(
      Func<IContext, IGenericManager<EntityOne>> entityOneGenericManagerFactory, 
      Func<IContext, IGenericManager<EntityTwo>> entityTwoGenericManagerFactory, 
      IEnumerable<Func<IContext, IGenericManager<BaseEntity>>> allGenericManagerFactories) 
     { 
      _entityOneGenericManagerFactory = entityOneGenericManagerFactory; 
      _entityTwoGenericManagerFactory = entityTwoGenericManagerFactory; 
      _allGenericManagerFactories = allGenericManagerFactories; 
     } 

     public void Run() 
     { 
      // !!!!!!!!!!!!!!! the collection _allGenericManagerFactories only contains the one factory for BaseEntity or empty depending on registration type 
      var list = new List<IGenericManager<BaseEntity>>(); 
      foreach (var genericManagerFactory in _allGenericManagerFactories) 
      { 
       var entity = genericManagerFactory(new Context()); 
       list.Add(entity); 
      } 
     } 
    } 

    internal class GenericManager<TEntity> : IGenericManager<TEntity> where TEntity : BaseEntity 
    { 
     private readonly IContext _context; 

     public GenericManager(IContext context) 
     { 
      _context = context; 
     } 

     public void Add(TEntity entity) 
     { 
      // entity gets added to the underlying context 
     } 

     public IEnumerable<TEntity> FindAllWithIncludeExpressions(Expression<Func<TEntity, bool>> filter = null, Func<IEnumerable<TEntity>, IOrderedEnumerable<TEntity>> orderBy = null, params Expression<Func<TEntity, object>>[] includeProperties) 
     { 
      return new TEntity[0]; 
     } 
    } 

    public interface IContext 
    { 
    } 

    internal class Context : IContext 
    { 

    } 

    public interface IGenericManager<TEntity> where TEntity : BaseEntity 
    { 
     void Add(TEntity entity); 
     IEnumerable<TEntity> FindAllWithIncludeExpressions(Expression<Func<TEntity, bool>> filter = null, Func<IEnumerable<TEntity>, IOrderedEnumerable<TEntity>> orderBy = null, params Expression<Func<TEntity, object>>[] includeProperties); 
    } 

    public abstract class BaseEntity 
    { 
    } 

    public class EntityOne : BaseEntity 
    { 

    } 

    public class EntityTwo : BaseEntity 
    { 

    } 

    public class EntityOnePointOne : EntityOne 
    { 

    } 
} 

ответ

0

Я пришел с довольно достойной работой вокруг с помощью шаблонов T4 и с помощью простого Autofac открытого общего метода регистрации, если кто-либо заинтересованы в ответе я буду рад опубликовать упрощенную версию этого здесь.

Смежные вопросы