【问题标题】:Returning The Appropriate Concrete Type For Abstract Generic Type为抽象泛型类型返回适当的具体类型
【发布时间】:2011-04-19 19:29:17
【问题描述】:

我在使用 StructureMap 配置时遇到了困难。我有一个接受 Func 作为其验证工厂的 ValidationProvider。我需要使用结构映射来提供它,以便它知道它应该返回的验证器(抽象)的实现。我想你已经很困惑了,所以这里有一些代码可以清除它们:

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

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

如您所见,验证提供程序将确定需要 IValidator 实现的功能委托给验证器工厂。我也有实现 IValidator 的 Validator。

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,当没有抽象验证器的实现时,它应该是默认的

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); 的那一行一直抛出这个异常:

结构图异常代码:202 否 定义的默认实例 插件家族 Sharwe.Services.Validation.Validator`1[[System.RuntimeType, mscorlib,版本=4.0.0.0, 文化=中性, PublicKeyToken=b77a5c561934e089]], Sharwe.Services,版本=1.0.0.0, Culture=neutral, PublicKeyToken=null

有什么办法可以把它连接起来?

P.S:如果有更简单的方法可以做到这一点,我会很高兴知道。这不是我实现的,我只是喜欢它,认为值得一试......

【问题讨论】:

    标签: c# dependency-injection inversion-of-control ioc-container structuremap


    【解决方案1】:

    更改以下代码:

    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 实例... uhhmm.. 还在关注我吗?异常消息实际上说明了一切:

    没有定义默认实例 验证器

    【讨论】:

    • @Steven:尽管这使它选择了正确的类型,但我仍然遇到几乎相同的错误,除了现在它告诉我没有为这种特定类型定义默认实例。看看这个,可能会有所帮助:i55.tinypic.com/343mewz.jpg
    • @Steven:我想我现在实际上更好地理解了这个错误,我需要找到一种方法来为 Validator 构建一个 BidValidator 实例...
    • @Kassem:我不确定您为什么会收到此错误,因为您似乎使用此行注册了 Validator&lt;Bid&gt;x.For&lt;Validator&lt;Bid&gt;&gt;().Use&lt;BidValidator&gt;();
    • @Steven:没错……这真的很奇怪……我希望 StructureMap 团队的人会看到这个问题并告诉我们出了什么问题……这没有意义!跨度>
    • @Kassem:您是否尝试过缩小范围以找到问题?以下是做什么的:var c = new Container(); c.Configure(r =&gt; r.For&lt;Validator&lt;Bid&gt;&gt;().Use&lt;BidValidator&gt;()); c.GetInstance&lt;Validator&lt;Bid&gt;&gt;(); ?
    【解决方案2】:

    我认为问题在于 ObjectFactory 和您创建的 Container 对象的混合使用...

    ObjectFactory 创建和管理一个容器实例,因此如果您创建另一个容器,它们将具有不同的配置。

    如果您只使用您的容器对象或只使用 ObjectFactory,它应该可以工作。

    【讨论】:

    • 我认为这实际上解决了问题!非常感谢人!但是,现在我仍然坚持(stackoverflow.com/questions/5720605/…)所以我无法完全测试它并检查问题是否完全解决。但至少该行不再抛出异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多