Unity注册非泛型接口的泛型类型

4
我的情况看起来(对我来说)非常简单,但我找不到解决办法。
我有这种情况:
public class Class<T> : IInterface where T : class
{ 

}

接口不能被泛型化(来自WCF库)。

因此我想像这样注册接口:

container.RegisterType(typeof (IInterface ), typeof (Class<>));

然后使用 T 解决它。

我该怎么做?我错过了什么吗?

我的意图是做类似于这样的事情

container.Resolve<IInterface>(/* specify T */);

你必须在Class<>中指定一个类型,以便typeof能够正常工作,可能你想将IInterface强制转换为特定类型的Class<T>,例如Class<Order>? - Daniel Dawes
不,我没有这样做 - 我想以通用的方式实现此接口,并且我需要T是动态的。 - Tom
1
@Tom:如果你不使用Unity,你会如何实现这个?请更新你的问题并附上展示此内容的代码。这可以帮助我们更好地理解你想要完成的目标。 - Steven
如果我不使用Unity,我会使用你建议的工厂。但是我认为Unity可以处理这个问题,因为我想在解析实例时告诉他T是什么。 - Tom
@Tom:你不能告诉Unity这个,也不应该告诉Unity这个。这就是工厂模式的设计初衷。 - Steven
2个回答

8

我错过了什么?

您缺少一个工厂。

想想看,没有魔法小精灵在背景中猜测您需要的类型。 您需要提供它。 要么通过像这样明确声明配置时的T

container.RegisterType(
    typeof(IInterface),
    typeof(Class<SomeType>));

或者在运行时创建一个工厂,将T传递给它:

public interface IInterfaceFactory
{
    IInterface Create<T>();
}

工厂可以按照以下方式注册:
container.RegisterInstance<IInterfaceFactory>(
    new InterfaceFactory(container));

可以如下实现:

public class InterfaceFactory : IInterfaceFactory
{
    private readonly IUnityContainer container;
    public InterfaceFactory(IUnityContainer container)
    {
        this.container = container;
    }

    public IInterface Create<T>()
    {
        return this.container.Resolve<Class<T>>();
    }
}

现在,您可以将 IInterfaceFactory 注入到需要使用 IInterface 的消费者中,他们可以通过调用 Create<T>() 方法请求他们需要的版本。 更新 如果您认为这太多代码了,您也可以按以下方式注册一个工厂委托:
container.RegisterInstance<Func<Type, IInterface>>(
    type => container.Resolve(
        typeof(Class<>).MakeGenericType(type)));

这基本上是相同的,但现在内联在一个委托中。您的消费者现在可以依赖于Func<Type, IInterface>而不是IInterfaceFactory,并将类型实例传递给委托。

个人而言,我更喜欢使用描述性接口,如IInterfaceFactory。这取决于您。


你的解决方案看起来对我来说太复杂了。我希望Unity可以为我完成这个任务 - 我将解决实际的T,以便Unity可以将其注入到已在接口上注册的类中。 - Tom
1
在我看来,这是非常优雅的解决方案! - Steven Ryssaert
优秀的解决方案! - Valo

8

如果您不需要使用不受控制的接口进行解析,则可以创建自己的受控接口,该接口使用泛型并派生自不受控制的接口。然后,您可以注册开放式泛型并解析闭合式泛型类型。

public interface IControlled<T> : IUncontrolled {}
public class Controlled<T> : IControlled<T> {}

container.RegisterType(typeof(IControlled<>), typeof(Controlled<>));

IUncontrolled instance = container.Resolve<IControlled<string>>();

伟大 - 简单而优雅 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接