2015-04-21 28 views
2

我想寫一個JobActivator HangFire使用ServiceStack IoC和我無法解決類型。我相信對於那些對泛型有更多經驗的人來說,這將是一個簡單的答案。如何解決類型使用ServiceStack Funq IoC

我傳遞中的容器,從HostContext.Container來

using Hangfire; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using ServiceStack; 

namespace Common.Hangfire 
{ 

    public class FunqJobActivator : JobActivator 
    { 

     private Funq.Container _container; 

     public FunqJobActivator(Funq.Container container) 
     { 
      if (container == null) 
      { 
       throw new ArgumentNullException("container"); 
      } 
      _container = container; 
     } 

     public override object ActivateJob(Type type) 
     { 
      return _container.Resolve<type>(); //** this doesn't compile 
     } 
    } 
} 
+0

Funq'的'作爲IoC框架的選擇是在這種情況下不幸。許多IoC框架將提供一個'Resolve'方法,它接受'Type'作爲它的參數。我不相信Funq。它依賴泛型方法參數來獲取類型。 – Alex

回答

0

我想你想獲得T,並返回一個T

public T ActivateJob<T>() where T : class 
{ 
    return _container.Resolve<T>(); 
} 
2

我會建議使用不同IoC框架,因爲Funq不支持採用Type參數的解析方法,即它不具有方法

object Container.Resolve(Type theType); 

因此,與遲髮型的婚姻是一個困難的,因爲遲髮型不提供,你可以使用爲過載:

virtual T ActivateJob<T>() where T : class 

如果你堅持要用Funq,這可能是(低效率)解決像這樣的:

public class FunqJobActivator : JobActivator 
{ 
    private const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; 
    private static readonly _activateMethod = 
     typeof(FunqJobActivator).GetMethod("InternalActivateJob", flags); 

    private Funq.Container _container; 

    public FunqJobActivator(Funq.Container container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException("container"); 
     } 
     _container = container; 
    } 

    public override object ActivateJob(Type type) 
    { 
     // this will allow calling InternalActivateJob<T> with typeof(T) == type. 
     var method = _activateMethod.MakeGenericMethod(new [] { type }); 
     return method.Invoke(this, null); 
    } 

    private object InternalActivateJob<T>() where T : class 
    { 
     return _container.Resolve<T>(); 
    } 
} 
+0

感謝@Alex,因爲我在這裏使用ServiceStack,所以我不想添加另一個IoC,因爲它是內置的。 – brussell

+0

@brussell好的,那麼我想你將不得不使用基於反射的方法,就像上面的代碼塊一樣。 – Alex

3

雖然Funq是一個類型的國際奧委會與通用的API,你可以添加一個輔助擴展方法,使解決使用運行時類型,如實例:

public static class ContainerExtensions 
{ 
    public static object TryResolve(this Container container, Type type) 
    { 
     var mi = typeof(Container).GetMethods(BindingFlags.Public | BindingFlags.Instance) 
      .First(x => x.Name == "TryResolve" && 
        x.GetGenericArguments().Length == 1 && 
        x.GetParameters().Length == 0); 

     var genericMi = mi.MakeGenericMethod(type); 
     var instance = genericMi.Invoke(container, new object[0]); 
     return instance; 
    } 
} 

,這將使您解決註冊依賴使用運行時類型,e.g:

var container = new Container(); 
container.Register(c => new Foo()); 

var instance = container.TryResolve(typeof(Foo)); 
+0

感謝@mythz工作。由於我正在解決這個ServiceStack服務以外的問題,因此我應該在實例解決後調用_container.AutoWire(instance)嗎? – brussell

+0

@brussell這與直接調用'TryResolve '泛型方法相同。它的解析方式不會影響它的註冊方式,即依賴關係將處於相同的狀態,無論它解決了哪個API。 – mythz