在(数据)注释使用Unity的依赖注入 [英] Using Unity's dependency injection in (data) annotations

查看:462
本文介绍了在(数据)注释使用Unity的依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的统一,并有标记的数据注释的型号:

I am using Unity and have a Model tagged with data annotations:

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

这SlackDisplayName属性是一个子类显示名称,它解决了静态展示名称为属性。我只是想让动态有了这个条件满足:

This SlackDisplayName property is a child class of DisplayName, which resolves a static Display Name for the property. I just wanted to make that dynamically by having this criteria fulfilled:


  1. 使用这种注释是有可能的

  2. 我可以使用注解实现多语言应用程序。

  3. 语言模板得到由一个GUID

  4. 确定我不能传递文化的ID注释

  1. The use of this annotation is possible.
  2. I can implement multilingual applications using that annotation.
  3. Language templates get identified by a GUID
  4. I must not pass a culture id to the annotation

所以此外,我SlackDisplayName注释是这样的:

So furthermore, my SlackDisplayName annotation looks like this:

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

和现在的问题是:如何从我的团结集装箱得到ICultureContext:

And now the question is: How to get the ICultureContext from my Unity Container:

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

有注册,但我不知道如何获得该财产注入线索。

It is registered, but I have no clue about how to get that property injected.

推荐答案

我已经解决了它自己!

首先,你需要的以下统一推广和策略:

First of all, you need the following Unity Extension and Strategy:

资讯:这里找到的 UnityContainer.BuildUp() - ?我可以把它注入新的实例为属性只,如果这些都为空

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

}

您需要这个,因为它是负责的堆积注入的属性。接下来这一点,你需要注册你的扩展

You need this, because it is responsible for injecting the properties on "BuildUp". Next to this, you need to register your extension

container.AddNewExtension<RecursiveBuildUpContainerExtension>();



此外,你需要重写默认DataAnnotationsModelMetadataProvider,因为默认ModelMetaDataProvider不使用统一注入性质到注解。要做到这一点,实现这个类:

Furthermore, you need to override the default DataAnnotationsModelMetadataProvider, because the default ModelMetaDataProvider does not use Unity to inject properties to annotations. To do this, implement this class:

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框架:

After that, edit your bootstrapper and set the new ModelMetadataProvider, to make it clear to the MVC Framework that it has to use it:

ModelMetadataProviders.Current = new DynamicModelMetadataProvider(container);



在哪里容器的设置IUnityContainer。你现在应该有实例的注解实例时已经设置标有[InjectionMethod]应该得到所谓的[DependencyAttribute]和你的方法。

Where container is your set up IUnityContainer. You should now have instances in your Annotations Instance when having set the [DependencyAttribute] and your Methods marked with the [InjectionMethod] should get called.

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



希望你可以使用这个,如果你有类似的问题;)

Hope you could use this if you had a similar problem ;)

这篇关于在(数据)注释使用Unity的依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆