2

このようなクラスをデシリアライズしています

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

オブジェクトを BuildUp() すると、プロパティが null の場合にのみ Unity に AnotherClass の新しいインスタンスを作成させ、それ以外の場合は BuildUp を実行させます。これを達成する簡単な方法はありますか?

編集: wpf で mvvm を実行しています。クラスはビューモデルです。実行間で保持したいプロパティがいくつかあり、ユニティに注入したい依存関係もいくつかあるため、それらをシリアル化します。したがって、逆シリアル化の後、ネストされたモデルはプロパティが設定された状態で既にそこにあるため、ユニティが新しいインスタンスでそれをオーバーライドすることは望ましくありませんが、それでもその上で InjectionMethods を呼び出し、プログラムが最初に実行されたときに正常に解決する必要があります。ネストされたモデルは null です。

4

3 に答える 3

3

私はユニティ拡張機能を書くことになりました。これを行う方法に関するドキュメントがあまり見つからなかったため、結果についてはよくわかりません。それはうまくいくようですが、私は何か恐ろしいことを書いたかもしれないと感じています..とにかく、コードは次のとおりです。改善を歓迎します:

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

    }
于 2011-08-24T21:04:11.597 に答える
1

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、リフレクションを使用してすべてのプロパティを注入するため、高速ではない可能性があることに注意してください;-)

于 2011-08-22T21:29:35.860 に答える
0

簡単な方法はありますか?いいえ。

生成されたilを編集し、既存のオブジェクトを検出する必要があります...それは可能ですが、決して単純ではありません。

于 2011-08-21T16:26:17.633 に答える