返回抽象泛型类型的适当具体类型

发布于 2024-11-02 11:43:48 字数 3148 浏览 3 评论 0原文

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

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

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

正如您所看到的,验证提供程序将确定需要哪种 IValidator 实现的功能委托给 validatorFactory。我还有实现 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,当没有抽象 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 否 默认实例定义为 插件家族 Sharwe.Services.Validation.Validator`1[[System.RuntimeType, mscorlib,版本=4.0.0.0, 文化=中立, PublicKeyToken=b77a5c561934e089]], Sharwe.Services,版本=1.0.0.0, 文化=中性,PublicKeyToken=null

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

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

I'm having a hard time with StructureMap configuration. I have a ValidationProvider that accepts a Func as its validation factory. I need to supply that using structure map so it would know what implementation of Validator (abstract) it should return. I guess you're already confused so here's some code to clear things out:

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

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

As you can see, the validation provider delegates the functionality of figuring out what implementation of IValidator is required to the validatorFactory. I also have Validator which implements 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);
}

Then I have a Validator instance for each entity that requires validation, example:

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.");
    }
}

And I've got a NullValidator which is supposed to be the default when there is no implementation of the abstract Validator

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

So now in StructureMap I need to tie things up together, but I cannot get it to work... Here's what I got:

            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)));

But the line that says return (IValidator) ObjectFactory.GetInstance(valType); keeps throwing this exception:

StructureMap Exception Code: 202 No
Default Instance defined for
PluginFamily
Sharwe.Services.Validation.Validator`1[[System.RuntimeType,
mscorlib, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b77a5c561934e089]],
Sharwe.Services, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null

Any way I could get this hooked up?

P.S: if there's an easier way to do this, I'll be glad to know about it. This was not implemented by me, I just liked it and thought is worth giving a shot...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最偏执的依靠 2024-11-09 11:43:48

将以下代码更改

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

没有定义默认实例
验证器

Change the following code:

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

To:

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

You are supplying a Type argument and calling type.GetType() which will return type Type instance of that Type... uhhmm.. still following me? The exception message actually says it all:

No Default Instance defined for
Validator<System.RuntimeType>

听不够的曲调 2024-11-09 11:43:48

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

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

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

I think the problem is mixed usage of ObjectFactory and the Container object you created...

ObjectFactory creates and manages a container instance, so if you create another container they will have different configuration.

If you use only your container object or only ObjectFactory it should work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文