简体   繁体   English

如何使用ServiceStack Funq IoC解析类型

[英]How to resolve type using ServiceStack Funq IoC

I'm trying to write a JobActivator for HangFire using ServiceStack IoC and I'm having trouble resolving from a type. 我正在尝试使用ServiceStack IoC编写用于HangFire的JobActivator, 无法从类型中解析。 I'm sure this will be an easy answer for someone with more experience with generics. 我相信这对于拥有更多泛型经验的人来说是一个简单的答案。

The container I'm passing in is coming from HostContext.Container 我传入的容器来自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
        }
    }
}

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, eg: 虽然Funq是具有通用API的类型化IOC,但是您可以添加一个辅助程序扩展方法,以启用使用运行时类型的实例解析,例如:

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, eg: 这将允许您使用运行时类型来解析注册的依赖关系,例如:

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

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

I would recommend using a different IoC framework, because Funq does not support a resolve method that takes a Type argument, ie it does not have a method 我建议使用其他IoC框架,因为Funq不支持带有Type参数的resolve方法,即它没有方法

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: 因此,与Hangfire联姻是一件困难的事情,因为Hangfire不会提供您可以用作的重载:

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

If you insist on using Funq, this can be (inefficiently) solved like this: 如果您坚持使用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>();
    }
}

I think you want to get a T and to return a T 我认为您想获得T并返回T

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM