返回抽象泛型类型的适当具体类型
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将以下代码更改
为
:您提供一个
Type
参数并调用type.GetType()
,这将返回该Type
类型实例代码>类型...呃..还在关注我吗?异常消息实际上说明了一切:Change the following code:
To:
You are supplying a
Type
argument and callingtype.GetType()
which will return typeType
instance of thatType
... uhhmm.. still following me? The exception message actually says it all:我认为问题在于 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.