在(数据)注释中使用Unity的dependency injection

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

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

此SlackDisplayName属性是DisplayName的子类,它解析属性的静态显示名称。 我只是想通过满足这个标准来动态地做到这一点:

  1. 可以使用此注释。
  2. 我可以使用该注释实现多语言应用程序。
  3. 语言模板由GUID标识
  4. 我不能将文化ID传递给注释

所以,我的SlackDisplayName注释看起来像这样:

 ///  /// Annotation for non-fixed display names ///  public class SlackDisplayNameAttribute : DisplayNameAttribute { ///  /// TODO ///  ///  public SlackDisplayNameAttribute(String identifierGUID) : this(Guid.Parse(identifierGUID)) { } ///  /// TODO ///  ///  public SlackDisplayNameAttribute(Guid identifier) : base() { } ///  /// The culture context to use. ///  [Dependency] public ICultureContext Context { get; set; } ///  /// Gets the display name for the given GUID. ///  public override string DisplayName { get { return "NOT_DEFINED"; //return Context.GetLanguageTemplate(new Guid()); } } } 

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

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

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

我自己解决了!

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

信息 :在此处找到: 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( 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( 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( IEnumerable objects ){ foreach (var o in objects){ if( o is T ) return true; } return false; } } 

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

 container.AddNewExtension(); 

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

 public class DynamicModelMetadataProvider : DataAnnotationsModelMetadataProvider { private IUnityContainer _context; protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func 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]时在Annotations Instance中有实例,并且应该调用标有[InjectionMethod]的方法。

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

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