在自定义属性中应用带Unity的DI

时间:2016-02-07 10:03:54

标签: c# unity-container

嗨,我是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);
        }
    }

4 个答案:

答案 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框架。但是我喜欢这个解决方案。

Auto data contract

答案 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; }
}

FluentValidation示例:

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接线就位。这可以引入极大的灵活性。阅读有关与成员连接属性的其他文章。