Возврат соответствующего конкретного типа для абстрактного общего типа - PullRequest
2 голосов
/ 19 апреля 2011

Мне тяжело с конфигурацией StructureMap. У меня есть ValidationProvider, который принимает Func в качестве фабрики проверки. Мне нужно предоставить это, используя структурную карту, чтобы он знал, какую реализацию Validator (абстрактную) он должен вернуть. Я думаю, вы уже сбиты с толку, так что вот код, чтобы прояснить ситуацию:

public class ValidationProvider : IValidationProvider
{
    private readonly Func<Type, IValidator> _validatorFactory;

    public ValidationProvider(Func<Type, IValidator> validatorFactory)
    {
        _validatorFactory = validatorFactory;
    }

Как вы можете видеть, поставщик валидации делегирует функциональность для определения того, какая реализация IValidator требуется для validatorFactory. У меня также есть Validator, который реализует IValidator.

public abstract class Validator<T> : IValidator
{
    IEnumerable<ValidationResult> IValidator.Validate(object entity)
    {
        if (entity == null) throw new ArgumentNullException("entity");

        return this.Validate((T)entity);
    }

    protected abstract IEnumerable<ValidationResult> Validate(T entity);
}

Затем у меня есть экземпляр Validator для каждой сущности, требующей проверки, например:

public sealed class BidValidator : Validator<Bid>
{
    protected override IEnumerable<ValidationResult> Validate(Bid bid)
    {
        if (bid.User.HasEnoughCredits(bid.Item.Category.ListingPrice) == false)
            yield return new ValidationResult("InsufficientCredits", "Not enough credits.");
        if(bid.Item.IsValidBidAmount(bid.Amount) == false)
            yield return new ValidationResult("Amount", "Bid amount has to be higher than last posted bid.");
        if(bid.User.OwnsItem(bid.Item.Id))
            yield return new ValidationResult("InvalidBidder", "User cannot bid on his/her own items.");
    }
}

И у меня есть NullValidator, который должен быть по умолчанию, когда нет реализации абстрактного Validator

public sealed class NullValidator<T> : Validator<T>
{
    protected override IEnumerable<ValidationResult> Validate(T entity)
    {
        return Enumerable.Empty<ValidationResult>();  
    }
}

Так что теперь в StructureMap мне нужно связать вещи вместе, но я не могу заставить его работать ... Вот что я получил:

            x.For(typeof(Validator<>)).Use(typeof(NullValidator<>));
            x.For<Validator<Bid>>().Use<BidValidator>();
            x.For<Validator<Rating>>().Use<RatingValidator>();
            x.For<Validator<TopLevelCategory>>().Use<TopLevelCategoryValidator>();
        });

        Func<Type, IValidator> validatorFactory = type =>
        {
            var valType = typeof(Validator<>).MakeGenericType(type.GetType());
            return (IValidator) ObjectFactory.GetInstance(valType);
        };

        container.Configure(x => x.For<IValidationProvider>().Use(() => new ValidationProvider(validatorFactory)));

Но строка с надписью return (IValidator) ObjectFactory.GetInstance(valType); продолжает выдавать это исключение:

Код исключения StructureMap: 202 Нет Экземпляр по умолчанию, определенный для PluginFamily Sharwe.Services.Validation.Validator`1 [[System.RuntimeType, mscorlib, версия = 4.0.0.0, Culture = нейтрально, PublicKeyToken = b77a5c561934e089]], Sharwe.Services, версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = ноль

В любом случае, я мог бы это подключить?

P.S .: если есть более простой способ сделать это, я буду рад узнать об этом. Это не было реализовано мной, мне просто понравилось, и я подумал, что стоит попробовать ...

Ответы [ 2 ]

2 голосов
/ 20 апреля 2011

Измените следующий код:

Func<Type, IValidator> validatorFactory = type =>
{
    var valType = typeof(Validator<>).MakeGenericType(type.GetType());
    return (IValidator) ObjectFactory.GetInstance(valType);
};

Кому:

Func<Type, IValidator> validatorFactory = type =>
{
    var valType = typeof(Validator<>).MakeGenericType(type);
    return (IValidator) ObjectFactory.GetInstance(valType);
};

Вы предоставляете Type аргумент и вызываете type.GetType(), который будет возвращать тип Type экземпляра этого Type ... ммм ... все еще следует за мной? Сообщение об исключении фактически говорит обо всем:

Экземпляр по умолчанию не определен для Validator

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

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

ObjectFactory создает и управляет экземпляром контейнера, поэтому при создании другого контейнера они будут иметь другую конфигурацию.

Если вы используете только свой контейнерный объект или только ObjectFactory, он должен работать.

...