在(数据)注释使用Unity的依赖注入 [英] Using Unity's dependency injection in (data) annotations
问题描述
我使用的统一,并有标记的数据注释的型号:
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:
- 使用这种注释是有可能的
- 我可以使用注解实现多语言应用程序。
- 语言模板得到由一个GUID
- 确定我不能传递文化的ID注释
- The use of this annotation is possible.
- I can implement multilingual applications using that annotation.
- Language templates get identified by a GUID
- 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屋!