C# 在自定义属性中使用Unity应用DI

C# 在自定义属性中使用Unity应用DI,c#,unity-container,C#,Unity Container,嗨,我是新来的统一DI。我正在开发一个自定义属性。在该属性中,我希望借助Unity注入一个依赖项。但当在类中使用该属性时,会显示异常。代码是: public interface ITest { } public class AAttrib : Attribute { ITest _test; public AAttrib(ITest test) { _test = test;

嗨,我是新来的统一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
    }
例外情况是:

没有给出与所需的形式化参数相对应的参数 “AAttrib.AAttribITest”的参数“test”

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

不能对属性使用依赖项注入,因为属性是扩展类的元信息的元信息。这些元信息是在编译时生成的

您不能对属性使用依赖注入,因为属性是扩展类元信息的元信息。这些元信息是在编译时生成的,在属性中使用DI确实是不可能的。然而,使用装饰器有一个很好的干净的解决方法

请参阅此博客:

我试过这个,我已经用了很长时间了。你将能够用这个做你需要的事情


博客有.net framework和.net核心解决方案,实际上不可能在属性中使用DI。然而,使用装饰器有一个很好的干净的解决方法

请参阅此博客:

我试过这个,我已经用了很长时间了。你将能够用这个做你需要的事情

博客上有.net框架和.net核心解决方案

为迟到道歉。 不确定团结是否能让你这么做。但PostSharp有办法做到这一点。我从未尝试过这一点,因为PostSharp在我的项目中不是一个经批准的DI框架。但我喜欢这个解决方案

为迟到道歉。 不确定团结是否能让你这么做。但PostSharp有办法做到这一点。我从未尝试过这一点,因为PostSharp在我的项目中不是一个经批准的DI框架。但我喜欢这个解决方案


这并不能回答您的问题,但却为您正在思考的解决方案提供了不同的视角

您应该避免使用属性。属性是很好的起点,但会妨碍应用程序扩展。 属性是硬编码的,并且至少违反了两个坚实的原则,即单一责任原则和开放/封闭原则。它应该使用流畅的API来完成

我宁愿用流畅的API替换AAttrib

属性示例 FluentValidation示例:
这本质上与属性所做的事情相同。在正确的DI接线到位的情况下。这可以带来很大的灵活性。阅读其他关于与成员关联属性的文章。

这并不能回答您的问题,但可以从不同的角度看待您正在思考的解决方案

您应该避免使用属性。属性是很好的起点,但会妨碍应用程序扩展。 属性是硬编码的,并且至少违反了两个坚实的原则,即单一责任原则和开放/封闭原则。它应该使用流畅的API来完成

我宁愿用流畅的API替换AAttrib

属性示例 FluentValidation示例:
这本质上与属性所做的事情相同。在正确的DI接线到位的情况下。这可以带来很大的灵活性。阅读关于与成员连接属性的其他文章。

考虑属性注入而不是依赖项的构造函数注入。你能给我一个例子吗?与其通过构造函数初始化_测试,不如声明属性[Dependency]ITest _测试{get;set},Unity将注入该属性。请注意Property上的Dependency属性Consider属性注入,而不是依赖项的构造函数注入。您能给我一个示例吗?与其通过构造函数初始化_测试,不如声明属性[Dependency]ITest _测试{get;set},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);
        }
    }
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"));
    }
}