StructureMap -> EnrichWith слишком много обогащает (другие случаи) - PullRequest
5 голосов
/ 26 марта 2009
// Enrich with is enriching more than i want

public intefrace ICommand {
   void Execute();
}

// classes

public class A : ICommand {}
public class B : ICommand {}
public class MultiCommand : ICommand {
  public MultiCommand(ICommand[] commands) {}
}

// -- decorators
public DecoratorOne : ICommand {
  public DecoratorOne(Icommand toDecorate) {}
}

public DecoratorTwo : ICommand {
  public DecoratorOne(Icommand toDecorate) {}
}



// what i tried

 ForREquesedType<ICommand>()
    .TheDefaultIsConcreteType<A>
    .EnrichWith(x => new DecoratorOne(x)
    .EnrichWith(y => new DecoratorTwo(y)
    .CacheBy(InstanceScope.Singleton);

 InstanceOf<ICommand>()
    .TheDefault.Is.OfConcreteType<B>
    .EnrichWith(x => new DecoratorOne(x)
    .WithName("secondCommand")

            ForRequestedType<MultiCommand>()
                .TheDefault.Is.OfConcreteType<MultiCommand>()
                .TheArrayOf<ICommand>()
                .Contains(y =>
                              {
                                  y.TheDefault();
                                  y.TheInstanceNamed("secondCommand")
                              })
                .WithName("multi");

**

/// что я хочу сделать

**

Что я хочу, так это то, что A - это значение по умолчанию. Так что в любом месте, где требуется экземпляр ICommand, он получит A. MultiCommand будет иметь как A, так и B, и выполнит их в цикле.

**

// проблема у меня

**

Б, кажется, украшен несколько раз. Когда я звоню ObjectFactory.GetNamedInsance<ICommand>("secondCommand") я получаю что-то новое **new DecoratorOne(new DecorateOne(B)).** Я предполагаю, что это оформлено из-за определения, которое я имею по умолчанию, A. Как я могу избежать этот?

Кроме того, это правильный способ для вставки массива в мультикоманду?

Еще раз спасибо, я новичок в структуре карты, поэтому любая помощь будет оценена.

UPDATE

В итоге я создал подкласс TypeInterceptor, который соответствующим образом декорировал типы. Мне это не кажется правильным, но это лучше, чем использовать «новый» в моем коде. Таким образом, код превратился в

        RegisterInterceptor(new CommandDecoratorInterceptor());

        // this is the default that everyone hooks into
        ForRequestedType<ICOmmand>()
            .TheDefaultIsConcreteType<A>()
            .CacheBy(StructureMap.Attributes.InstanceScope.Singleton);

        InstanceOf<ICommand>()
            .Is.OfConcreteType<B>()
            .WithName("secondCommand");


        ForRequestedType<MultiCommand>()
            .TheDefault.Is.OfConcreteType<MultiCommand>()
            .TheArrayOf<ICommand>()
            .Contains(y =>
                          {
                              y.TheDefault();
                              y.TheInstanceNamed("secondCommand");
                          });

И тогда новый перехватчик Типа декорирует классы, как и раньше. Это позволяет MultiMonitor избегать обесцвечивания (обогащения).

Любые предложения по улучшению этого будут оценены;)

1 Ответ

4 голосов
/ 27 марта 2009

Не используйте TheDefaultIsConcreteType перед обогащением. Это все равно что делать это сразу после ForRequestedType (), который говорит, что вы хотите обогатить все ICommands. Вместо этого используйте TheDefault.Is.OfConcreteType.

Также не удваивайте Enrich, он не очень хорошо цепляется при замене экземпляров. Для вашего сценария должно работать следующее:

    ForRequestedType<ICommand>()
        .CacheBy(StructureMap.Attributes.InstanceScope.Singleton)
        .TheDefault.Is.OfConcreteType<A>()
        .EnrichWith(x => new DecoratorTwo(new DecoratorOne(x)));
    InstanceOf<ICommand>().Is
        .OfConcreteType<B>()
        .EnrichWith(x => new DecoratorOne(x))
        .WithName("second");
    InstanceOf<ICommand>().Is
        .OfConcreteType<MultiCommand>()
        .TheArrayOf<ICommand>().Contains(y =>
        {
            y.TheDefault();
            y.TheInstanceNamed("second");
        })
        .WithName("multi");
...