如何将 Unity 与内部 类 一起使用?
How can I use Unity with internal classes?
我有一个 Web API 应用程序,正在使用 Unity 进行依赖注入。该应用程序使用包含接口 IDoStuff 和实现接口的 class 的库:
internal interface IDoStuff
{
void DoSomething();
}
internal class DoStuff : IDoStuff
{
public void DoSomething()
{
// Do some stuff
}
}
图书馆还有一个 public class 需要做的事情:
public class NeedToDoStuff
{
private IDoStuff doStuff;
public NeedToDoStuff()
{
this.doStuff = new DoStuff();
}
internal NeedToDoStuff(IDoStuff doStuff)
{
this.doStuff = doStuff;
}
void PleaseDoStuff()
{
doStuff.DoSomething();
}
}
我想使用 Unity 在我的控制器中创建一个 NeedToDoStuff 实例,并负责在内部创建 DoStuff class,而不是直接调用 new 的构造函数。但是,我能看到的唯一方法是同时创建 IDoStuff 接口和 DoStuff class public 这对我来说似乎是错误的。这似乎是错误的,因为这些是实现细节并且只与库本身相关。我知道通过控制反转,您允许顶级应用程序通过某种配置来选择其底层实现,但这是否意味着不再需要内部等?
暂时忘记您正在使用容器,假设您 create those classes yourself in the startup path 您的应用程序。你将如何在 C# 中实际执行此操作?
答案是,你不能。这将不会在 C# 中编译,因为 C# 要求这些类型为 public。因此,尽管这些类型可能是其他组件的实现细节,但它们不是将它们连接在一起的应用程序部分的实现细节。您是否使用 DI 库来帮助您是无关紧要的;该库需要访问这些库,因为对于库来说,那些 类 是 而不是 实现细节。
请注意,有不同的隐藏方式 类。您可以将接口移动到它们自己的程序集中,并让使用库和包含实现的库都依赖于新的 'contract' 程序集。当您不让使用程序集依赖于实现程序集时,实现类型实际上对使用程序集隐藏了,即使这些类型仍然是 public.
我已经发布了我自己的答案,因为我认为它最接近回答我原来的问题。它可能不像 Steven 的建议那样是一个干净的设计选择,但不管你喜欢它还是讨厌它,它确实允许库的内部 类 与 Unity 结合使用。
我需要对 classes/interfaces 进行三个更新:
- 制作接口public。
- 构造函数public.
- 引入一个静态 class/method,它在库中执行统一注册,从应用程序启动时执行的主要统一注册逻辑调用。
虽然我个人反对内部接口,但您可以通过添加
允许统一使用它们
[assembly: InternalsVisibleTo("Unity_ILEmit_InterfaceProxies")]
到包含您的接口的项目的 AssemblyInfo.cs 文件。我在尝试添加 [assembly: InternalsVisibleTo("Microsoft.Practices.Unity")] 后发现了这个
我看到它在其他 post 中不起作用并且没有效果,但我觉得这是正确的方向。我从我的代码中提取的堆栈跟踪引用了上面的程序集并允许代码工作。
这将允许您隐藏您的界面。构造函数是另一回事了。
我有一个 Web API 应用程序,正在使用 Unity 进行依赖注入。该应用程序使用包含接口 IDoStuff 和实现接口的 class 的库:
internal interface IDoStuff
{
void DoSomething();
}
internal class DoStuff : IDoStuff
{
public void DoSomething()
{
// Do some stuff
}
}
图书馆还有一个 public class 需要做的事情:
public class NeedToDoStuff
{
private IDoStuff doStuff;
public NeedToDoStuff()
{
this.doStuff = new DoStuff();
}
internal NeedToDoStuff(IDoStuff doStuff)
{
this.doStuff = doStuff;
}
void PleaseDoStuff()
{
doStuff.DoSomething();
}
}
我想使用 Unity 在我的控制器中创建一个 NeedToDoStuff 实例,并负责在内部创建 DoStuff class,而不是直接调用 new 的构造函数。但是,我能看到的唯一方法是同时创建 IDoStuff 接口和 DoStuff class public 这对我来说似乎是错误的。这似乎是错误的,因为这些是实现细节并且只与库本身相关。我知道通过控制反转,您允许顶级应用程序通过某种配置来选择其底层实现,但这是否意味着不再需要内部等?
暂时忘记您正在使用容器,假设您 create those classes yourself in the startup path 您的应用程序。你将如何在 C# 中实际执行此操作?
答案是,你不能。这将不会在 C# 中编译,因为 C# 要求这些类型为 public。因此,尽管这些类型可能是其他组件的实现细节,但它们不是将它们连接在一起的应用程序部分的实现细节。您是否使用 DI 库来帮助您是无关紧要的;该库需要访问这些库,因为对于库来说,那些 类 是 而不是 实现细节。
请注意,有不同的隐藏方式 类。您可以将接口移动到它们自己的程序集中,并让使用库和包含实现的库都依赖于新的 'contract' 程序集。当您不让使用程序集依赖于实现程序集时,实现类型实际上对使用程序集隐藏了,即使这些类型仍然是 public.
我已经发布了我自己的答案,因为我认为它最接近回答我原来的问题。它可能不像 Steven 的建议那样是一个干净的设计选择,但不管你喜欢它还是讨厌它,它确实允许库的内部 类 与 Unity 结合使用。
我需要对 classes/interfaces 进行三个更新:
- 制作接口public。
- 构造函数public.
- 引入一个静态 class/method,它在库中执行统一注册,从应用程序启动时执行的主要统一注册逻辑调用。
虽然我个人反对内部接口,但您可以通过添加
允许统一使用它们[assembly: InternalsVisibleTo("Unity_ILEmit_InterfaceProxies")]
到包含您的接口的项目的 AssemblyInfo.cs 文件。我在尝试添加 [assembly: InternalsVisibleTo("Microsoft.Practices.Unity")] 后发现了这个 我看到它在其他 post 中不起作用并且没有效果,但我觉得这是正确的方向。我从我的代码中提取的堆栈跟踪引用了上面的程序集并允许代码工作。
这将允许您隐藏您的界面。构造函数是另一回事了。