Как легко управлять адаптерами и / или декораторами с параметрами времени выполнения? - PullRequest
3 голосов
/ 08 декабря 2011

Я приведу очень простой пример.

class Implementation: IMyInterface
{
    string mArg;

    public Implementation(string arg)
    {
        mArg = arg;
    }

    public DoStuff(object param)
    {
        // snip
    }
}

class Decorator: IMyInterface
{
    IMyInterface mWrapped;

    public Decorator(IMyInterface wrapped)
    {
        mWrapped = wrapped;
    }

    public DoStuff(object param)
    {
        var result = mWrapped.DoStuff(param);

        // snip

        return result;
    }
}

Теперь аргумент, который мне нужен для конструктора реализации, я получаю от пользователя во время выполнения.

IMyInterface GetMyObject()
{
    string arg = AskUserForString();

    return mContext.Resolve // HOW?
}

Так что же является правильнымспособ установить это и разрешить экземпляр Decorated?

Пример прост.Но представьте себе, что есть больше слоев (декораторов / адаптеров), и для внутренней реализации необходим параметр, который я получаю во время выполнения.

Ответы [ 3 ]

5 голосов
/ 29 января 2012

Я предполагаю, что вы используете автофак, как это указано в тегах вопроса. Вы можете попробовать что-то вроде этого:

public class ImplementationFactory
{
    private readonly IComponentContext container;

    public ImplementationFactory(IComponentContext container)
    {
        this.container = container;

    }
    public IMyInterface GetImplementation(string arg)
    {
        return container.Resolve<IMyInterface>(new NamedParameter("arg", arg));            
    }
}

И учетная / разрешающая часть:

var builder = new ContainerBuilder();
builder.RegisterType<ImplementationFactory>();
builder.RegisterType<Implementation>().Named<IMyInterface>("implementation");

builder.Register((c, args) => new Decorator(c.ResolveNamed<IMyInterface>("implementation", args.First())))
    .As<IMyInterface>();

var container = builder.Build();

var factory = container.Resolve<ImplementationFactory>();
var impl = factory.GetImplementation("abc"); //returns the decorator

Если у вас есть несколько декораторов, вы можете связать их в порядке, который вы хотите при регистрации:

builder.Register((c, args) => new Decorator(c.ResolveNamed<IMyInterface>("implementation", args.First())));
builder.Register((c, args) => new SecondDecorator(c.Resolve<Decorator>(args.First()))).As<IMyInterface>();

Вот хорошая статья о поддержке декоратора в autoofac .

5 голосов
/ 08 декабря 2011

Вы можете создать объект фабрики для реализации и каждого из ваших декораторов, и заставить фабрики декораторов действовать как декораторы для фабрики реализации и просто передать входные данные в вызов разрешения. Те, которые вы, вероятно, настроите при запуске приложения или в каком-либо файле конфигурации.

Чтобы быть очень гибким, я бы сделал фабрику, которая берет

Func<IMyInterface, IMyInterface>

или даже

Func<IMyInterface, string, IMyInterface>)

чтобы он мог создать любую имплементацию IMyInterface, которую вы хотите.

Так что-то вроде этого

interface IMyInterfaceFactory
{
   IMyInterface Resolve(string parameter);
}

class DecoratorFactory : IMyInterfaceFactory
{
   IMyInterfaceFactory parent;

   Func<IMyInterface, string, IMyInterface> resolver;

   public DecoratorFactory(
      IMyInterfaceFactory parent, 
      Func<IMyInterface, string, IMyInterface> resolver)
   {
      this.parent = parent;
      this.resolver= resolver;
   }

   public IMyInterface Resolve(string parameter)
   {
      var decoratee = parent.Resolve(parameter);

      return resolver(decoratee, parameter);
   }
}

И если вам нужны более сложные операции в методе Resolve, такие как выбор между несколькими родителями или делегатами распознавателя, тогда вы можете просто сделать другую реализацию фабричного интерфейса для них.

1 голос
/ 30 января 2012

Что не так с простой передачей параметра в метод interface.DoStuff.Поскольку аргумент представляется обязательным и не является квалификатором для конкретной реализации интерфейса, вы можете просто добавить другой параметр в метод DoStuff.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...