编程语言
首页 > 编程语言> > c#-在(数据)注释中使用Unity的依赖项注入

c#-在(数据)注释中使用Unity的依赖项注入

作者:互联网

我正在使用Unity并具有一个标有数据注释的模型:

public class SomeModel
{    
   [SlackDisplayName("ED0CAD76-263E-496F-ABB1-A4DFE6DEC5C2")]
   public String SomeProperty { get; set; }    
}

此SlackDisplayName属性是DisplayName的子类,该类解析该属性的静态显示名称.我只是想通过满足以下条件来动态地做到这一点:

>可以使用此注释.
>我可以使用该注释来实现多语言应用程序.
>语言模板由GUID标识
>我不得将文化ID传递给注释

因此,此外,我的SlackDisplayName注释如下所示:

/// <summary>
/// Annotation for non-fixed display names
/// </summary>
public class SlackDisplayNameAttribute : DisplayNameAttribute
{
    /// <summary>
    /// TODO
    /// </summary>
    /// <param name="identifierGUID"></param>
    public SlackDisplayNameAttribute(String identifierGUID)
        : this(Guid.Parse(identifierGUID))
    {
    }

    /// <summary>
    /// TODO
    /// </summary>
    /// <param name="identifier"></param>
    public SlackDisplayNameAttribute(Guid identifier)
        : base()
    { 

    }

    /// <summary>
    /// The culture context to use.
    /// </summary>
    [Dependency]
    public ICultureContext Context { get; set; }

    /// <summary>
    /// Gets the display name for the given GUID.
    /// </summary>
    public override string DisplayName
    {
        get
        {
            return "NOT_DEFINED";
            //return Context.GetLanguageTemplate(new Guid()); 
        }
    }
}

现在的问题是:如何从我的Unity容器中获取ICultureContext:

[Dependency]
public ICultureContext Context { get; set; }

它已注册,但是我不知道如何注入该属性.

解决方法:

我自己解决了!

首先,您需要以下Unity扩展和策略:

信息:在这里找到:UnityContainer.BuildUp() – Can I make it inject new instances into properties only if these are null?

public class RecursiveBuildUpContainerExtension : UnityContainerExtension {
    protected override void Initialize(){
        Context.Strategies.Add( new RecursiveBuildUpBuilderStrategy( Context.Container ), UnityBuildStage.PreCreation );
    }
}

public class RecursiveBuildUpBuilderStrategy : BuilderStrategy {
    readonly IUnityContainer container;
    public RecursiveBuildUpBuilderStrategy( IUnityContainer container ) {
        this.container = container;
    }

    public override void PreBuildUp( IBuilderContext context ) {

        if( context.Existing == null ) return;

        foreach( var prop in context.Existing.GetType( ).GetProperties( ) ) {

            if( ContainsType<DependencyAttribute>( prop.GetCustomAttributes( true ) ) ) {

                if( prop.GetValue( context.Existing, null ) == null ) {
                    var value = container.Resolve( prop.PropertyType );
                    prop.GetSetMethod( ).Invoke( context.Existing, new[] { value } );
                }
                else {
                    var value = container.BuildUp( prop.PropertyType, prop.GetValue( context.Existing, null ) );
                    prop.GetSetMethod( ).Invoke( context.Existing, new[] { value } );
                }
            }
        }

        foreach (var method in context.Existing.GetType().GetMethods() ){
            if( ContainsType<InjectionMethodAttribute>( method.GetCustomAttributes( true ))){
                var argsInfo = method.GetParameters( );
                var args = new object[argsInfo.Length];

                for( int i = 0; i < argsInfo.Length; i++ ) {
                    args[i] = container.Resolve( argsInfo[i].ParameterType );
                }

                method.Invoke( context.Existing, args );
            }
        }

        context.BuildComplete = true;
    }

    private static bool ContainsType<T>( IEnumerable<object> objects ){
        foreach (var o in objects){
            if( o is T ) return true;
        }
        return false;
    }

}

您需要这样做,因为它负责在“ BuildUp”上注入属性.在此旁边,您需要注册您的扩展程序

container.AddNewExtension<RecursiveBuildUpContainerExtension>();

此外,您需要覆盖默认的DataAnnotationsModelMetadataProvider,因为默认的ModelMetaDataProvider不使用Unity将属性注入注解.为此,请实现此类:

public class DynamicModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    private IUnityContainer _context;

    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {           
        foreach (Attribute attribute in attributes)
            _context.BuildUp(attribute);

        return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
    }

    public DynamicModelMetadataProvider(IUnityContainer context)
        : base()
    {
        this._context = context;
    }
}

之后,编辑您的引导程序并设置新的ModelMetadataProvider,以向MVC框架明确说明它必须使用它:

ModelMetadataProviders.Current = new DynamicModelMetadataProvider(container);

容器是在其中设置IUnityContainer的.现在,在设置[DependencyAttribute]时,注释实例中应该有实例,并且应调用标有[InjectionMethod]的方法.

[Dependency]
public ICultureContext Context { get; set; }

希望如果您遇到类似的问题,可以使用它;)

标签:unity-container,c,asp-net-mvc
来源: https://codeday.me/bug/20191123/2064369.html