2014-12-03 87 views
4

Autofac documentation我可以看到如何讓所有註冊了一類T:解決所有給出的類型

public T[] ResolveAll<T>() 
{ 
    return _container.Resolve<IEnumerable<T>>().ToArray(); 
} 

但是,當我只有可用的類型,我怎麼能得到同等的結果?

public Array ResolveAll(Type service) 
{ 
    return _container.Resolve(??? 
} 

我想實現一個包裝類,它有一個預定義的接口。


編輯

對於快速參考,從馬修沃森答案(由大衛大號相關的想法)是:

public Array ResolveAll(Type service) 
{ 
    var typeToResolve = typeof(IEnumerable<>).MakeGenericType(service); 
    return _container.Resolve(typeToResolve) as Array;  
} 
+0

請參見[56,「問題‘’包括在他們的頭銜?」標籤(http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles ),那裏的共識是「不,他們不應該」! – 2016-02-11 16:54:06

+0

[獲取實現某個接口的所有註冊對象的列表]的可能重複(http://stackoverflow.com/questions/24369861/get-a-list-of-all-registered-objects-implementing-a-certain-接口) – 2016-02-11 17:02:02

回答

1

下面是一個例子。我已經添加斷言證明返回類型從ResolveAll<T>(this IContainer self)是相同的(在同一順序)返回那些從ResolveAll(this IContainer self, Type type)

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using Autofac; 
using Autofac.Core; 

namespace AutofacTrial 
{ 
    public abstract class Base 
    { 
     public abstract string Name { get; } 

     public override string ToString() 
     { 
      return Name; 
     } 
    } 

    public sealed class Derived1: Base 
    { 
     public override string Name 
     { 
      get 
      { 
       return "Derived1"; 
      } 
     } 
    } 

    public sealed class Derived2: Base 
    { 
     public override string Name 
     { 
      get 
      { 
       return "Derived2"; 
      } 
     } 
    } 

    public sealed class Derived3: Base 
    { 
     public override string Name 
     { 
      get 
      { 
       return "Derived3"; 
      } 
     } 
    } 

    static class Program 
    { 
     static void Main() 
     { 
      var builder = new ContainerBuilder(); 

      builder.RegisterType<Derived1>().As<Base>(); 
      builder.RegisterType<Derived2>().As<Base>(); 
      builder.RegisterType<Derived3>().As<Base>(); 

      var container = builder.Build(); 

      var array1 = container.ResolveAll(typeof(Base)); 
      var array2 = container.ResolveAll<Base>(); 

      Trace.Assert(array1.Length == 3); 
      Trace.Assert(array2.Length == 3); 

      for (int i = 0; i < array1.Length; ++i) 
      { 
       Trace.Assert(array1[i].GetType() == array2[i].GetType()); 
       Console.WriteLine(array1[i]); 
      } 
     } 

     public static T[] ResolveAll<T>(this IContainer self) 
     { 
      return self.Resolve<IEnumerable<T>>().ToArray(); 
     } 

     public static object[] ResolveAll(this IContainer self, Type type) 
     { 
      Type enumerableOfType = typeof(IEnumerable<>).MakeGenericType(type); 
      return (object[]) self.ResolveService(new TypedService(enumerableOfType)); 
     } 
    } 
} 

下屬執行相同

我也使用Reflector看的Resolve<IEnumerable<T>>()實施,它捲起這樣做:

public static TService Resolve<TService>(this IComponentContext context, IEnumerable<Parameter> parameters) 
{ 
    return (TService) context.Resolve(typeof(TService), parameters); 
} 

的呼叫:

public static object Resolve(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters) 
{ 
    return context.ResolveService(new TypedService(serviceType), parameters); 
} 

於是兩人必須等同,因爲它們實現的方式。

+0

這不等於'_container.Resolve >()'?可能會錯過一些東西,但我試圖解決如何獲得所有註冊時,我擁有的只是一個類型。 – Appetere 2014-12-03 17:04:01

+0

@Steve你嘗試過嗎?我發佈的代碼將返回一個帶有兩個解析對象的數組,其中一個是NonPerishableProduct類型,另一個是PerishableProduct類型,即所有可實現「IProduct」的可解析具體類。這不是你想要的嗎? – 2014-12-04 08:47:48

+0

@Steve我添加了一個簡單的例子,證明它*是*等價的。 – 2014-12-04 09:12:40

1

您可以通過反射(MSDN)調用包裝方法來調用_container.Resolve,但這樣做會失去編譯時類型的安全性。

public class Container 
{ 
    public T[] ResolveAll<T>() 
    { 
     return _container.Resolve<IEnumerable<T>>().ToArray(); 
    } 

    public object ResolveAllGeneric(Type t) 
    { 
     MethodInfo method = GetType().GetMethod("ResolveAll") 
          .MakeGenericMethod(new Type[] { t }); 
     return method.Invoke(this, new object[] { }); 
    } 
} 
相關問題