嗨,我是DI的团结新手。我正在开发一个自定义属性。在该属性中,我想在Unity的帮助下注入依赖项。但是当在类中使用该属性时,它会显示异常。代码是:
public interface ITest
{
}
public class AAttrib : Attribute
{
ITest _test;
public AAttrib(ITest test)
{
_test = test;
}
}
public class Test : ITest
{
}
[AAttrib]
public class Example
{
// to do
}
例外是:
没有任何论据符合所要求的形式 参数' test' ' AAttrib.AAttrib(ITest)
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITest, Test>(new HierarchicalLifetimeManager());
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
Unity解析器类是:
public class UnityResolver: IDependencyResolver
{
protected IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
if(container == null)
throw new ArgumentNullException("container");
this._container = container;
}
public void Dispose()
{
_container.Dispose();
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException r)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new UnityResolver(child);
}
}
答案 0 :(得分:3)
您不能在属性上使用依赖注入,因为属性是扩展类的元信息的元信息。这些元信息是在编译期间生成的
答案 1 :(得分:1)
确实不可能在属性中使用DI。但是,通过使用装饰器,有一个很好的解决方法。
查看此博客:https://blogs.cuttingedge.it/steven/posts/2014/dependency-injection-in-attributes-dont-do-it/
我尝试了这个,现在已经使用了一段时间了。您将可以完全按照自己的需要去做。
(博客具有.net框架和.net核心解决方案)
答案 2 :(得分:1)
道歉迟到。 不知道团结是否可以让你做到这一点。但是PostSharp可以实现这一目标。我从来没有尝试过,因为PostSharp并不是我项目中认可的DI框架。但是我喜欢这个解决方案。
答案 3 :(得分:0)
这不能回答您的问题,但是可以为您正在考虑的解决方案提供不同的视角。
您应避免使用属性。属性是一个很好的起点,但会妨碍应用程序扩展。 属性是硬编码的,并且至少违反了两个SOLID原则:单一职责和开放/封闭原则。而是应该使用Fluent API来完成
我宁愿用Fluent API代替AAttrib。
public class Person {
[StringLength(100)]
[RegularExpression("^([a-zA-Z0-9 .&'-]+)$", ErrorMessage = "Invalid First Name")]
public string FirstName { get; set; }
}
public class Person {
public string FirstName { get; set; }
}
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.FirstName).NotNull().WithMessage("Can't be null");
RuleFor(x => x.FirstName).Length(1, 100).WithMessage("Too short or long");
RuleFor(x => x.FirstName).Matches("^([a-zA-Z0-9 .&'-]+)$").WithMessage("Invalid First Name"));
}
}
这实际上将执行属性所执行的相同操作。正确的DI接线就位。这可以引入极大的灵活性。阅读有关与成员连接属性的其他文章。