Unity Container Регистрация с именами не работает, а без имени работает нормально - PullRequest
0 голосов
/ 07 апреля 2019

Я знаю, это звучит глупо. Я приведу несколько фрагментов кода и постараюсь объяснить как можно больше.

Реализация № 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 не может разрешить

Я открыл конструктор Registrations, и все зависимости

Вопросы

  1. Правильно ли я использую именную регистрацию?
  2. Передача имени так проста? Просто передайте строку при регистрации, и та же самая строка при разрешении должна работать.
  3. Как мне отладить / разрешить это?

Пример кода

Program.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();
    }

Startup.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());
        }
    }

Message ReaderWriter

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:\Code\HelloDI\HelloDIApp\HelloDIApp.ConsoleClient\Program.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();
}

1 Ответ

0 голосов
/ 08 апреля 2019

Нашел один способ сделать это.Я все еще ищу ответы.

При построении сложных объектов мы можем сообщать единству о том, как мы хотим определить наши зависимости.Мы можем поиграть со всеми комбинациями разных имен и создать карту зависимостей.После разрешения 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();
}
...