4

我想要实现的是:

[Factory]
public interface IFooFactory
{
    Foo Create();
}

unityContainer.RegisterType<IFooFactory>(
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<FactoryInterceptionBehavior>());

没有实现的地方IFooFactory- 因为它是由FactoryInterceptionBehavior.

但是,当我尝试解决此问题IFooFactory时,我收到一条ResolutionFailedException消息:

InvalidOperationException - 当前类型 IFooFactory 是一个接口,无法构造。您是否缺少类型映射?

我还考虑过自己创建代理(使用Intercept.ThroughProxy<>或城堡动态代理...),但我仍然需要对容器进行类型注册。我不知道如何委托/覆盖这种类型的实例化(如 Ninject 的Bind<IFoo>().ToMethod(() => return new Foo()))。

4

1 回答 1

1

因此,经过一些研究和反复试验,我发现Unity.Interception不支持没有实现接口的实际类以及调用最终结束的接口代理(城堡动态代理称它们为“没有接口代理”目标”)。

所以我所做的是使用Castle.Core动态代理与统一的开箱即用InjectionFactory(可用于将解决方案委托给Func工厂)。

注射工厂如下所示:

var proxyFuncFactory = new InjectionFactory(CreateProxy);

private static object CreateProxy(IUnityContainer container, Type interfaceType, string name)
{
    var proxyGenerator = container.Resolve<Castle.DynamicProxy.ProxyGenerator>();

    return proxyGenerator.CreateInterfaceProxyWithoutTarget(interfaceType, container.Resolve<AutoGeneratedFactoryInterceptor>());
}

并且可以在这样的绑定中使用:

IUnityContainer.RegisterType<ISomeFactory>(proxyFuncFactory);

AutoGeneratedFactoryInterceptor看起来像:

internal class AutoGeneratedFactoryInterceptor : IInterceptor
{
    private readonly IUnityContainer _unityContainer;

    public AutoGeneratedFactoryInterceptor(IUnityContainer unityContainer)
    {
        _unityContainer = unityContainer;
    }

    public void Intercept(IInvocation invocation)
    {
        IEnumerable<ResolverOverride> resolverOverrides = DetermineResolverOverrides(invocation);

        Type typeToResolve = DetermineTypeToResolve(invocation.Method);

        invocation.ReturnValue = _unityContainer.Resolve(typeToResolve, resolverOverrides.ToArray());
    }

    private static Type DetermineTypeToResolve(MethodInfo method)
    {
        ResolveToAttribute resolveToAttribute = method.Attribute<ResolveToAttribute>();
        if (resolveToAttribute == null)
        {
            return method.ReturnType;
        }

        if (resolveToAttribute.ResolveTo.IsGenericTypeDefinition)
        {
            return resolveToAttribute.ResolveTo.MakeGenericType(method.GetGenericArguments());
        }

        return resolveToAttribute.ResolveTo;
    }

    private static IEnumerable<ResolverOverride> DetermineResolverOverrides(IInvocation invocation)
    {
        return invocation.Method.Parameters()
            .Select((parameterInfo, parameterIndex) => 
                new ParameterOverride(parameterInfo.Name, invocation.Arguments[parameterIndex]));
    }

它按名称将 factory-method-argument 与 constructor-arguments 匹配(Unity out-of-the-box ParameterOverride)。请注意,尤其是通用参数支持并不完美。它支持以下用法:

public interface IFooFactory
{
    Foo Create();
}

unityContainer.RegisterType(typeof(IFoo<>), typeof(Foo<>));

public interface IFooFactory
{
    IFoo<T> Create<T>();
}

public interface IFooFactory
{
    Foo Create(string parameter1, object parameter2);
}

public interface IFooFactory
{
    [ResolveTo(typeof(Foo))]
    IFoo Create();
}

public interface IFooFactory
{
    [ResolveTo(typeof(Foo<>))]
    IFoo Create<T>();
}

另请注意,已解析(创建)实例的任何构造函数参数都没有被ParameterOverride's 覆盖,它们都是“像往常一样”的 ctor-inject。

于 2014-08-18T11:47:27.390 回答