c# - Using Unity's dependency injection in (data) annotations -
i using unity , have model tagged data annotations:
public class somemodel { [slackdisplayname("ed0cad76-263e-496f-abb1-a4dfe6dec5c2")] public string someproperty { get; set; } }
this slackdisplayname property child class of displayname, resolves static display name property. wanted make dynamically having criteria fulfilled:
- the use of annotation possible.
- i can implement multilingual applications using annotation.
- language templates identified guid
- i must not pass culture id annotation
so furthermore, slackdisplayname annotation looks this:
/// <summary> /// annotation 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> /// culture context use. /// </summary> [dependency] public iculturecontext context { get; set; } /// <summary> /// gets display name given guid. /// </summary> public override string displayname { { return "not_defined"; //return context.getlanguagetemplate(new guid()); } } }
and question is: how iculturecontext unity container:
[dependency] public iculturecontext context { get; set; }
it registered, have no clue how property injected.
i have solved myself!
first of all, need following unity extension , strategy:
info: found here: unitycontainer.buildup() - can make inject new instances properties if these 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 = 0; < 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 t ) return true; } return false; } }
you need this, because responsible injecting properties on "buildup". next this, need register extension
container.addnewextension<recursivebuildupcontainerextension>();
furthermore, need override default dataannotationsmodelmetadataprovider, because default modelmetadataprovider not use unity inject properties annotations. this, implement 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; } }
after that, edit bootstrapper , set new modelmetadataprovider, make clear mvc framework has use it:
modelmetadataproviders.current = new dynamicmodelmetadataprovider(container);
where container set iunitycontainer. should have instances in annotations instance when having set [dependencyattribute] , methods marked [injectionmethod] should called.
[dependency] public iculturecontext context { get; set; }
hope use if had similar problem ;)
Comments
Post a Comment