How to resolve type using ServiceStack Funq IoC

前端 未结 3 903
粉色の甜心
粉色の甜心 2021-01-21 23:20

I\'m trying to write a JobActivator for HangFire using ServiceStack IoC and I\'m having trouble resolving from a type. I\'m sure this will be an easy answer for someone with mo

相关标签:
3条回答
  • 2021-01-22 00:08

    Whilst Funq is a typed IOC with Generic API's, you can add a helper extension method to enable resolving instances using a runtime type, e.g:

    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;
        }
    }
    

    Which will allow you to resolve registered dependencies using a runtime Type, e.g:

    var container = new Container();
    container.Register(c => new Foo());
    
    var instance = container.TryResolve(typeof(Foo));
    
    0 讨论(0)
  • 2021-01-22 00:15

    I think you want to get a T and to return a T

    public T ActivateJob<T>() where T : class
    {
        return _container.Resolve<T>();  
    }
    
    0 讨论(0)
  • 2021-01-22 00:17

    I would recommend using a different IoC framework, because Funq does not support a resolve method that takes a Type argument, i.e. it does not have a method

    object Container.Resolve(Type theType);
    

    Thus the marriage with Hangfire is a difficult one, since Hangfire does not provide an overload that you could use as:

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

    If you insist on using Funq, this can be (inefficiently) solved like this:

    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 讨论(0)
提交回复
热议问题