2015-04-21 26 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