UnityContainer.BuildUp() - 仅当属性为空时,我可以让它将新实例注入到属性中吗?

发布于 2024-11-30 22:11:41 字数 407 浏览 6 评论 0原文

我正在反序列化这样一个类

class AClass{
    [Dependency]
    AnotherClass Property{ get; set; }
}

,当我使用 BuildUp() 对象时,我希望 Unity 仅在属性为 null 时创建 AnotherClass 的新实例,否则仅对其执行 BuildUp。 有没有一种简单的方法可以实现这一目标?

编辑:我正在用 wpf 做 mvvm 。这些类是视图模型,我将它们序列化,因为我想在运行之间保留一些属性,并且它们还有一些我想要统一注入的依赖项。因此,在反序列化之后,嵌套模型已经存在并设置了属性,因此我不希望 Unity 用新实例覆盖它,但我仍然希望它在其上调用 InjectionMethods 并在程序第一次运行时正常解析它,嵌套模型为空。

I'm deserializing a class like this one

class AClass{
    [Dependency]
    AnotherClass Property{ get; set; }
}

When I then BuildUp() the object I'd like Unity to create a new instance of AnotherClass only if the property is null and otherwise just perform a BuildUp on it.
Is there a simple way to achieve this?

Edit: I'm doing mvvm with wpf. The classes are view-models, I serialize them as there are some properties I want to preserve between runs and they also have some dependencies I want unity to inject. So after deserialization the nested model is already there with properties set so I don't want unity to override it with a new instance but I still want it to call InjectionMethods on it and also to resolve it normally the first time the program is run and the nested models are null.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只是一片海 2024-12-07 22:11:41

我最终写了一个统一扩展。
我找不到太多关于如何执行此操作的文档,所以我不太确定结果。
它似乎有效,但我有这种感觉我可能写了一些可怕的东西..
无论如何,这是代码,欢迎改进:

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

    }

I ended up writing a unity extension.
I could not find much documentation on how to do this so I'm not really sure about the result.
It seems to work but I have this feeling I might have written something horrible..
Anyway here's the code, improvements are welcome:

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

    }
绻影浮沉 2024-12-07 22:11:41

您可以编写自己的 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);

我没有测试甚至没有编译此代码,但它应该可以解决问题。请注意,由于它每次都会迭代所有注册并使用反射注入所有属性,因此它可能不是最快的事情;-)

You can write your own BuildUp method, like this:

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

Usage:

var instance = new AClass();

container.BuildUpButSkipInitializedProperties(instance);

I didn't test or even compile this code, but it should pretty much do the trick. Note that since it iterates all Registrations every time and injects all properties using reflection, it might not be the fasted thing ;-)

离旧人 2024-12-07 22:11:41

有简单的方法吗?不,

您需要编辑生成的 il,检测已经存在的对象...这是可以完成的,但绝不简单。

Is there a simple way? No.

You'd need to edit the generated il, detect already existing objects... It could be done but it's in no way simple.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文