在Unity中注册一个内部类?

3
你如何在Unity容器中从不同的程序集中注册内部类?
UnityContainer container = new UnityContainer();
container.RegisterType<IPublicInterface, InternalClassImpl>(new ContainerControlledLifetimeManager());

如果InternalClassImpl可以在它的程序集外部访问,那么这个方法非常好用。但是,如果它是internal的,并且实现了IPublicInterface,唯一的可行选择似乎是提供一个可以创建它们的工厂。

但是,如果您有一个工厂来创建类,如何继续使用Unity进行依赖注入来注入它的依赖关系呢?

大型应用程序

UnityContainer container = new UnityContainer();
container.RegisterType<IPublicInterface>(new InjectionFactory(c =>
InternalClassImplFactory.MakeInternalClassImpl()));

小型图书馆

namespace SmallLibrary
{
    public interface IPublicInterface
    {
    }

    public class InternalClassImplFactory
    {
        public static IPublicInterface MakeInternalClassImpl()
        {
            return new InternalClassImpl();
        }
    }

    internal class InternalClassImpl : IPublicInterface
    {
        public InternalClassImpl()
        {
        }
    }
}

但是如果InternalClassImpl需要从大型应用和内部SmallLibrary类中注入依赖项会发生什么呢?


你有 InternalsVisibleToAttribute 吗? - ProgrammingLlama
1
@john - 它在那里,但这会使内部事物在程序集外可见...我认为这是不好的做法...如果想要向外界公开,最好将其标记为public,为什么要使用那个属性呢? - Pranay Rana
@Pranay 但这正是Ryan要做的事情。他正在询问如何将另一个程序集中的内部实现添加到DI容器中。 - ProgrammingLlama
1
@john - 那最好公开化...我认为 - Pranay Rana
不,我在询问最佳实践以及如何最小化可见性并仅显示接口,同时仍然获得从LargeApplication依赖的构造类方法。 - Ryan Leach
好的,我误解了。 - ProgrammingLlama
2个回答

6
您需要使用UnityContainerExtension。 在定义了内部类的库中创建新的扩展。将您的内部类注册到容器中。
public class Extension : UnityContainerExtension
{
    protected override void Initialize()
    {
        Container.RegisterType<IPublicInterface, InternalClassImpl>();
    }
}


public interface IPublicInterface
{
}

internal class InternalClassImpl : IPublicInterface
{
    public InternalClassImpl()
    {
    }
}

现在,您可以通过 Extension 公开您的实现。因此,您的实现仍然是 internal,但您可以使用它。
static void Main(string[] args)
{
    var container = new UnityContainer();
    container.AddNewExtension<Extension>();
}

谢谢,这与我想象的相似。抱歉稍微编辑了一下问题,但是随着InternalClassImpl的增长,这是否也允许它依赖于LargeApplication和SmallLibrary? - Ryan Leach
1
@RyanTheLeach InternalClassImpl 由于其内部性质可以具有任何依赖关系。因此,这是隐藏契约实现的非常好的方式。 - Backs
你会如何处理生命周期?这是扩展的责任还是可以被父级覆盖? - Ryan Leach
2
@RyanTheLeach,你可以通过Extension类的构造函数传递LifeTimeManager并使用它。像这样注册:container.AddExtension(new Extension(new PerResolvelifeTimeManager())); - Backs

-1

虽然被接受的答案符合我的需求,但我认为另一种选择是让工厂方法获取容器。

public class InternalClassImplFactory
    {
        public static IPublicInterface MakeInternalClassImpl(IUnityContainer container)
        {
            return new InternalClassImpl();
        }
    }

在注册工厂方法时,c代表Unity容器! LargeApplication
container.RegisterType<IPublicInterface>(new InjectionFactory(c =>
InternalClassImplFactory.MakeInternalClassImpl(c)));

因此,您可以让工厂创建一个子容器,解决依赖关系或任何您需要的内容。


我认为这是另一个问题的解决方案。当你真正需要一个工厂时,而不是在你的情况下。 - Backs

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