带名称的 Unity 容器注册不起作用,而没有名称则工作正常



我知道这听起来很愚蠢。我将提供一些代码片段,并尝试解释尽可能多的内容。

实现 #1 - 没有名称

Container = new UnityContainer();
Container.RegisterType<IFirstInterface, FirstImplementation>();
Container.RegisterType<IDifferentAssemblyInterface, DifferentAssemblyImplementation>();
Container.RegisterType<ISameAssemblyInterface, SameAssemblyImplementation>();

实现 #2 - 带名称

const string configurationName = "simpleOption";
Container = new UnityContainer();
Container.RegisterType<IFirstInterface, FirstImplementation>(configurationName);
Container.RegisterType<IDifferentAssemblyInterface, DifferentAssemblyImplementation>(configurationName);
Container.RegisterType<ISameAssemblyInterface, SameAssemblyImplementation>(configurationName);

观察

实现#1工作得很好。我使用了即时窗口,一切都解决了。

在实现#2中,我使用了即时窗口,并且来自同一程序集的所有内容都可以解析

实现 #2 即时窗口无法准确解析 IDifferentAssemblyInterface 无法解析

我打开了注册构造函数,所有依赖项都是

问题

  1. 我是否正确使用命名注册?
  2. 传递名称就这么简单吗?只需在注册时传递一个字符串,解析期间相同的字符串应该可以工作。
  3. 如何调试/解决此问题?

示例代码

程序.cs

static IUnityContainer Container;
static void Main(string[] args)
{
// Arrange
Container = new UnityContainer();
Container.AddExtension(new Diagnostic());

Container.RegisterType<IMessageReader, ConsoleMessageReader>("Local");
Container.RegisterType<IMessageWriter, ConsoleMessageWriter>("Local");
Container.RegisterType<Startup, Startup>("Local");
Startup startup = Container.Resolve<Startup>("Local");
// Act
startup.Run();
}

启动.cs

public class Startup
{
IMessageReader _reader;
IMessageWriter _writer;
public Startup(IMessageReader reader, IMessageWriter writer)
{
_reader = reader;
_writer = writer;
}
public void Run()
{
_writer.WriteMessage(_reader.ReadMessage());
}
}

消息阅读器编写

public interface IMessageReader
{
string ReadMessage();
}
public class ConsoleMessageReader : IMessageReader
{
public string ReadMessage()
{
return "Hello, DI";
}
}
public interface IMessageWriter
{
void WriteMessage(string message);
}
public class ConsoleMessageWriter : IMessageWriter
{
public void WriteMessage(string message)
{
Console.WriteLine("{0}", message);
}
}

错误信息

Unhandled Exception: Unity.ResolutionFailedException: The current type, HelloDIApp.ConsoleClient.IMessageReader, is an interface and cannot be constructed. Are you missing a type mapping?
_____________________________________________________
Exception occurred while:
·resolving type:  'IMessageReader'
for parameter:  'reader'
on constructor:  Startup(IMessageReader reader, IMessageWriter writer)
resolving type:  'Startup' registered with name: 'Local'
---> System.InvalidOperationException: The current type, HelloDIApp.ConsoleClient.IMessageReader, is an interface and cannot be constructed. Are you missing a type mapping? ---> Unity.Exceptions.InvalidRegistrationException: Exception of type 'Unity.Exceptions.InvalidRegistrationException' was thrown.
--- End of inner exception stack trace ---
at Unity.Processors.ConstructorDiagnostic.<>c.<GetResolver>b__11_0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.UnityContainer.<>c__DisplayClass96_0.<OptimizingFactory>b__0(BuilderContext& c)
at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context)
at Unity.UnityContainer.ContextValidatingPlan(BuilderStrategy[] chain, BuilderContext& context)
at Unity.Builder.BuilderContext.Resolve(Type type, String name, InternalRegistration registration)
at Unity.Builder.BuilderContext.Resolve(Type type, String name)
at Unity.Builder.BuilderContext.Resolve(ParameterInfo parameter, Object value)
at Unity.Processors.ParametersProcessor`1.<>c__DisplayClass1_0.<CreateDiagnosticParameterResolvers>b__0(BuilderContext& context)
at Unity.Processors.ConstructorDiagnostic.<>c__DisplayClass12_0.<GetResolverDelegate>b__0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
at Unity.UnityContainer.<>c__DisplayClass96_0.<OptimizingFactory>b__0(BuilderContext& c)
at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context)
at Unity.UnityContainer.ExecuteValidatingPlan(BuilderContext& context)
--- End of inner exception stack trace ---
at Unity.UnityContainer.ExecuteValidatingPlan(BuilderContext& context)
at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type, String name, ResolverOverride[] overrides)
at Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, String name, ResolverOverride[] overrides)
at HelloDIApp.ConsoleClient.Program.Main(String[] args) in C:CodeHelloDIHelloDIAppHelloDIApp.ConsoleClientProgram.cs:line 18

工作代码

当我不使用名称时,它工作得很好。

static void Main(string[] args)
{
// Arrange
Container = new UnityContainer();
Container.AddExtension(new Diagnostic());
Container.RegisterType<IMessageReader, ConsoleMessageReader>();
Container.RegisterType<IMessageWriter, ConsoleMessageWriter>();
Container.RegisterType<Startup, Startup>();
Startup startup = Container.Resolve<Startup>();
// Act
startup.Run();
}

找到了一种方法。我仍在寻找答案。

在构造复杂对象时,我们可以告知 Unity 我们想要如何挑选我们的依赖项。我们可以尝试不同名称的所有组合并创建一个依赖映射。解析后,Unity 将完全按照该名称下的顺序进行构建。

static void Main(string[] args)
{
// Arrange
Container = new UnityContainer();
Container.AddExtension(new Diagnostic());

Container.RegisterType<IMessageReader, ConsoleMessageReader>();
Container.RegisterType<IMessageWriter, ConsoleMessageWriter>();
Container.RegisterType<IMessageReader, TwitterMessageReader>("Social");
Container.RegisterType<IMessageWriter, FacebookMessageWriter>("Social");
Container.RegisterType<IStartup, Startup>("Social", new InjectionConstructor(new ResolvedParameter<IMessageReader>("Social"), new ResolvedParameter<IMessageWriter>("Social")));
Container.RegisterType<IMessageReader, ConsoleMessageReader>("Local");
Container.RegisterType<IMessageWriter, ConsoleMessageWriter>("Local");
var reader = Container.Resolve<IMessageReader>("Social");
var writer = Container.Resolve<IMessageWriter>();
Container.RegisterType<IStartup, Startup>("Local", new InjectionConstructor(reader, writer));
IStartup startup = Container.Resolve<IStartup>("Local");
// Act
startup.Run();
}

最新更新