Виндзорская Типовая Фабрика - PullRequest
1 голос
/ 26 апреля 2011

Я пытаюсь преобразовать фабричный класс, который получает сообщение определенного типа и разрешает процессоры для этого типа сообщения, в реализацию Typed Factory Facility .

Код, с которого я начинаю:

public interface IProcessor<in T> where T : Message
{
    void Process(T message);
}

public class ProcessorFactory : IProcessorFactory
{
    private readonly IKernel _container;

    public ProcessorFactory(IKernel container)
    {
        if (container == null) throw new ArgumentNullException("container");

        _container = container;
    }

    public void Process(Message message)
    {
        // Create a specific message processor type
        var processorType = typeof(IProcessor<>).MakeGenericType(message.GetType());

        // Resolve all processors for that message
        var processors = _container.ResolveAll(processorType);

        foreach (var processor in processors)
        {
            processor.GetType().GetMethod("Process").Invoke(processor, new[] { message });
        }
    }

public class ProcessorInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
                Component.For<IProcessorFactory>().ImplementedBy<ProcessorFactory>(),
                AllTypes.FromThisAssembly().BasedOn(typeof(IProcessor<>)).WithService.FirstInterface().
                    AllowMultipleMatches());
    }
}

На основании следующих блогов и документации от Castle Windsor я создал следующее:

public interface IProcessor
{
    void Process();
}

public interface IProcessor<T> where T : Message
{
    /// <summary>
    /// Message to process
    /// </summary>
    T Message { get; set; }
}

public interface IProcessorFactory
{
    IProcessor[] GetAllProcessorsForMessage(Message message);
}

public class ProcessorInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<TypedFactoryFacility>()
            .Register(
                Component.For<ProcessorSelector, ITypedFactoryComponentSelector>(),
                Component.For<AutoReleaseProcessorInterceptor>(),

                AllTypes.FromThisAssembly()
                    .BasedOn(typeof(IProcessor<>))
                    .WithService.Base()
                    .Configure(c => c.LifeStyle.Is(LifestyleType.Transient)
                        .Interceptors<AutoReleaseProcessorInterceptor>()),

                Component.For<IProcessorFactory>().AsFactory(f => f.SelectedWith<ProcessorSelector>()));
    }
}

public class ProcessorSelector : DefaultTypedFactoryComponentSelector
{
    protected override Type GetComponentType(MethodInfo method, object[] arguments)
    {
        return typeof(IProcessor<>).MakeGenericType(arguments[0].GetType());
    }
}

Когда я звоню factory.GetAllProcessorsForMessage(new ExampleMessage()), я получаю следующую ошибку:

Невозможно привести объект типа 'Castle.Proxies.IProcessor`1Proxy' к типу 'MyNamespace.Processors.IProcessor []'.

Что я делаю не так и как можно улучшить код?

1 Ответ

1 голос
/ 27 апреля 2011

Это просто. Как говорится в сообщении об исключении, ваши прокси не поддерживают не универсальный интерфейс IProcessor. Вы должны сделать это сервисом и для этих компонентов.

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

Таким образом, метод вашего селектора должен иметь

.MakeArrayType() в конце.

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