[seasar-dotnet:2472] Re: S2Container/S2Dao 1.4.1, 1.3.20 リリース

kotani.k [E-MAIL ADDRESS DELETED]
2015年 10月 10日 (土) 22:52:02 JST


ohattaさん

小谷(koyak)です。

InjectionMapからinterfaceA -> implementsB
といく場合も
Implementation属性から implementsB -> implementsB
といく場合もDynamicProxyに対してはimplementsBとして
インスタンスを作らせにいくので、その辺りに原因がありそうですね。
恐らく先にInjectされた方が正しく動いているのではないかと思います。

Quill側でできそうな対応としては、
Implements(引数なし)でも、そのクラスがinterfaceの実装であれば
まずinterfaceでコンポーネントを探すようにする
or
Implements(引数なし)の場合、その型でインスタンスを作れなければ
interfaceの実装かチェック、interfaceの実装であればそちらで
コンポーネントを探すようにする

あたりが考えられますが、それはそれで利用の仕方によっては
予期せぬ動きをすることになると思うので対応しにくいですね。

ohattaさんが仰る通り、interfaceを実装されているのであれば、
interfaceを使ってでインスタンス変数を定義していただく方が、
モックを使っていた場合など、使用する実装クラスを別のものに入れ替えたいときに
変更もれがなくなる意味としても、intarfaceの存在意義としても良いのでは
ないかと思います。
(それは百もご承知の上でImplemtnsBを使う必要があるのだと思われますが。。。)

回避策としてはohattaさんが実施なさっている方法の他に、
MethodBもInterfaceAのメソッドにする(ExecuterCにはinterfaceでインスタンス変数をもつ)。
または、以下のような設計にすれば、DynamicProxyにインスタンスを作らせる型が
InjectionMapに登録しているものとは別になるので動作するのではないかと思います。

public class ImplementsB' : InterfaceA {
public void MethodA(){
XXXXXX
}
}
(InjectionMapにはInterfaceA-ImplementsB'で登録)

[Implementation]
public class ImplementsD : ImplementsB' {
public void MethodB(){
XXXXX
}
}
(もしくはInterfaceAの実装とし、
protected InterfaceA huga;
public void MethodA() { huga.MethodA(); }
とする)

[Implementation]
public class ExecutorC'
{
  protected ImplementsD hoge;
  public void Execute()
  {
    this.hoge.MethodB();
  }
}

以上です。

2015年10月8日 10:35 ohatta <ohatta+seasar.org.you @ gmail.com>:

> みなさま
> はじめまして、いつもお世話になります。pull requestをさせていただいた畑中です。
> 取込ありがとうございました。
>
> さて、pull requestをしておいて非常に申し訳ないのですが
> 1.3.20においてInjectionMapを使った特殊なケースで不具合が出る場合がありますので
> その報告と回避策のご相談をさせてください。
>
> interface InterfaceA{
>   void MethodA();
> }
>
> [Implementation]
> public class ImplementsB : InterfaceA
> {
>   protected ImplementsC ImplementsC;
>   public void MethodB()
>   {
>     this.ImplementsC.MethodC();
>   }
> }
>
> というクラスがあり、
> QuillInjector.GetInstance().InjectionMap.Add(typeof(InterfaceA),
> typeof(ImpelmentsB));
> と登録しておきながら
>
> [Implementation]
> public class ExecutorC
> {
>   protected ImplementsB ImplementsB;
>   public void Execute()
>   {
>     this.ImplementsB.MethodB();
>   }
> }
>
> 上記のようにInterfaceAではなく
> ImplmenetBを直接Injectしてもらう実装があると
> このImplementsBインスタンスが正しく初期化されない場合があります。
> 具体的には
> ImplementsB.ImplementsCにインスタンスがInjectされない場合があります。
> 今回の変更でDynamicProxyインスタンスを共有したことに原因があると思いますが
> 完全には原因をつかめていません。
>
> 回避策として
> public class ExecutorC
> {
>   protected InterfaceA ImplementsB;
> ・・・・
>
> と変更することで問題なく動くことを確認しました。
>
> ・そもそもinterfaceを定義するならinterfaceでInjectしてもらうのが正しい
> ・DynamicProxyのメモリリークがクリティカルになっている
> という理由でわれわれのプロジェクトは上記の回避策で対応していますが、
> こちら、大きな問題になりそうでしょうか?
>
> 一度ご検討いただければと思います。
>
> 以上、よろしくお願いします。
>
>
> 2015年9月25日(金) 0:33 kotani.k <keikotani926 @ gmail.com>:
>
>> 小谷(koyak)です。
>>
>> S2Container/S2Dao 1.4.1, 1.3.20をリリースしました。
>> http://s2container.net.seasar.org/ja/download.html
>>
>> 1.4.1は.NET4.0以上、1.3.20は.NET3.5以前で動作します。
>> また、動作はVisualStudio2013上で確認しています。
>>
>> 変更点は下記の通りです。
>>
>> S2Container.NET 1.4.1、1.3.20
>> *** Bug
>> [Issue#7] QuillInjector#Destroy()で破棄されないオブジェクトがある不具合修正。
>> (プルリクエストをいただいた分の反映です(ありがとうございました!))
>>
>> *** Improvement
>> [Issue#3] QuillのODP.NET管理対象ドライバへの対応(1.4.1のみ)
>>
>> S2DaoNET 1.4.1、1.3.20
>> 変更なし
>>
>> 以上です。
>> _______________________________________________
>> seasar-dotnet mailing list
>> seasar-dotnet @ ml.seasar.org
>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>
>
> _______________________________________________
> seasar-dotnet mailing list
> seasar-dotnet @ ml.seasar.org
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>
>
-------------- next part --------------
HTML$B$NE:IU%U%!%$%k$rJ]4I$7$^$7$?(B...
URL: <http://ml.seasar.org/archives/seasar-dotnet/attachments/20151010/ab97c707/attachment.html>


seasar-dotnet メーリングリストの案内