unitycontainer .积聚()-我可以使它注入新的实例到属性,只有当这些是空的
本文关键字:属性 实例 我可以 可以使 unitycontainer 注入 积聚 | 更新日期: 2023-09-27 18:06:19
我要反序列化一个像这样的类
class AClass{
[Dependency]
AnotherClass Property{ get; set; }
}
当我建立()对象时,我希望Unity只在属性为null时创建一个新的AnotherClass实例,否则只是对它执行一个建立。有没有简单的方法可以做到这一点?
编辑:我正在用wpf做mvvm。这些类是视图模型,我序列化它们,因为我想在运行之间保留一些属性,它们也有一些依赖关系,我想让unity注入。因此,在反序列化之后,嵌套模型已经在那里设置了属性,所以我不希望unity用一个新实例覆盖它,但我仍然希望它在它上调用InjectionMethods,并且在程序第一次运行时正常地解决它,嵌套模型为null。我最终写了一个unity扩展。我找不到很多关于如何做到这一点的文档,所以我不太确定结果。这似乎有效,但我有这种感觉,我可能写了一些可怕的东西…无论如何,这是代码,欢迎改进:
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
方法,如下所示:
public static void BuildUpButSkipInitializedProperties(
this UnityContainer container, object instance)
{
var registeredTypes = (
from registration in container.Registrations
select registration.RegisteredType)
.ToArray();
var injectableProperties =
from property in instance.GetType().GetProperties()
where property.GetGetMethod() != null
where property.GetSetMethod() != null
where property.GetValue(instance, null) == null
where registeredTypes.Contains(property.PropertyType)
select property;
foreach (var property in injectableProperties)
{
object value = container.Resolve(property.PropertyType);
property.SetValue(instance, value);
}
}
用法:
var instance = new AClass();
container.BuildUpButSkipInitializedProperties(instance);
我没有测试甚至没有编译这段代码,但它应该很好地完成了任务。请注意,由于它每次迭代所有Registrations
并使用反射注入所有属性,因此它可能不是最快速的事情;-)
有没有简单的方法?没有。
你需要编辑生成的文件,检测已经存在的对象…这是可以做到的,但这并不简单。