Car*_*son 4 c# generics dependency-injection decorator simple-injector
我正在尝试构建一个结构,其中我有一个基础IValidator <>接口,将基于一些元数据为我们的系统生成.我们希望给未来的开发人员灵活地1)重新生成IValidator <>如果需要的话的具体实现,而不会干扰任何手工编写的代码和2)添加装饰器来IValidator <>,以便能够扩展功能,而不会干扰自动生成的代码.
我希望有一些方法可以在运行时使用Simple Injector的RegisterDecorator方法来解析泛型装饰器,这样我们的开发团队就不需要每次添加装饰器时都更新组合根.
以下是一些示例类/接口
public interface IValidator<T> where T : class
{
void Validate(T entity);
}
public class ClientValidator : IValidator<Client>
{
public void Validate(Client entity)
{
//Auto-generated
}
}
public class UserValidator : IValidator<User>
{
public void Validate(User entity)
{
//Auto-generated
}
}
public class ClientValidatorDecorator : IValidator<Client>
{
private readonly IValidator<Client> clientValidator;
public ClientValidatorDecorator(IValidator<Client> clientValidator)
{
this.clientValidator = clientValidator;
}
public void Validate(Client entity)
{
//New rules
this.clientValidator.Validate(entity);
}
}
public class UserValidatorDecorator : IValidator<User>
{
private readonly IValidator<User> userValidator;
public UserValidatorDecorator(IValidator<User> userValidator)
{
this.userValidator = userValidator;
}
public void Validate(User entity)
{
//New rules
this.userValidator.Validate(entity);
}
}
public class ValidationContext
{
private readonly IValidator<Client> client;
private readonly IValidator<User> user;
public ValidationContext(IValidator<Client> client, IValidator<User> user)
{
this.client = client;
this.user = user;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试这样做:
public void RegisterServices(Container container)
{
container.Register(typeof(IValidator<>), AssemblyManifest.GetAssemblies());
container.RegisterDecorator(typeof(IValidator<>), GetType, Lifestyle.Transient, UseType);
}
private static Type GetType(DecoratorPredicateContext ctx)
{
//Return appropriate Decorator
}
private static bool UseType(DecoratorPredicateContext ctx)
{
//Predicate
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,除非我解决一个具体的类型RegisterDecorator抛出一个错误,所以解决另一个通用似乎.我不知道该怎么办.有没有办法做这样的事情?有没有更好的方法来获得没有装饰器的预期功能?我们在考虑部分课程,但这有一系列问题.
任何帮助将不胜感激!
您可以使用复合验证器来IValidator<>根据需要添加实现,而不是插入装饰器.此解决方案将允许代码包含IValidator<>相同类型的多个.
在内部,您的代码仍然可以依赖于一个IValidator<T>可以解析为CompositeValidator调用零或更多验证器的单个代码,具体取决于在运行时在容器中注册的内容.
复合验证器:
public class CompositeValidator<T> : IValidator<T>
{
public readonly IEnumerable<IValidator<T>> validators;
public CompositeValidator(IEnumerable<IValidator<T>> validators)
{
this.validators = validators;
}
public void Validate(T item)
{
foreach(var validator in this.validators)
{
validator.Validate(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
容器配置如下:
var assemblies = new[] { typeof(IValidator<>).Assembly };
var container = new Container();
container.RegisterCollection(typeof(IValidator<>), assemblies);
container.Register(typeof(IValidator<>), typeof(CompositeValidator<>));
Run Code Online (Sandbox Code Playgroud)
其中assemblies变量包含要搜索验证器的所有程序集.
当您解决IValidator<User>使用container.GetInstance<IValidator<User>>()或通过构造函数注入时,您将返回CompositeValidator<User>内部引用任何和所有内容 IValidator<User>的内容.
| 归档时间: |
|
| 查看次数: |
675 次 |
| 最近记录: |