C#相談室

このエントリーをはてなブックマークに追加
304デフォルトの名無しさん
>>74にもあるんだけど、アトリビュートってどういう時に使うものなの?
.NETのAPI見てるとかなりえげつないことやってるけど、
どうしてあんなことができるのか不思議だ。。。
305名無しさん♯:2001/05/24(木) 18:41
>>304
Attributeは大きく分けて2種類あるよん。

1つはCustom Attributeといって、exeとかdllにデータを直接埋め込んじゃうやつ。
んで、コンテナ側でリフレクションを使ってそのデータを吸い上げて、
そこで特殊な処理を行なう...といった感じ。

だから、「えげつないこと」は実はコンテナ側がやってる。

もう1つはContext Attributeといって、こちらは処理のインターセプトができる。
例えば、インスタンス起動とかメソッド実行の前後のタイミングを拾える(らしい)ので、
そこに特殊な処理を割り込ませることができる。

これはAttributeの実装側で「えげつないこと」をやることになると思う。

そういえば、漏れも前に「メソッドの終わりに来たら強制ガベコレ起動」なんていうのを
お遊びで作ったことがあるけど、下手すると本当に何でもありになるよ。(藁


...あまり答えになってないけど、こんなんでいい?
306デフォルトの名無しさん:2001/05/24(木) 21:29
>>305
何となくわかりました。
アトリビュートそのものに仕掛けを作ったり、受け側に仕掛けを作ったり
っちゅうことですね。

>「メソッドの終わりに来たら強制ガベコレ起動」
ソースあぷきぼーん
307名無しさん♯:2001/05/25(金) 11:26
>>306
別にいいけど、97%パクリソースだよ。(藁
元ネタは、Don Box先生の「UnwindScope Service」ね。

 http://www.develop.com/dbox/dotnet/unwind/


// ForceGC.cs

using System;
using System.Runtime.Remoting;

namespace ForceGC
{
  [ AttributeUsage(AttributeTargets.Class) ]
  public class ForceGCAttribute : ContextAttribute
  {
    public ForceGCAttribute() : base("ForceGCAttribute") {
    }

    public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg) {
      ctorMsg.ContextProperties.Add(new ForceGCProperty());
    }

    public override bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg) {
      return false;
    }
  }

  class ForceGCProperty : IContextProperty, IContributeObjectSink
  {
    public ForceGCProperty() {
    }

    public string Name {
      get { return "ForceGC"; }
    }

    public void Freeze(Context newCtx) {
    }

    public bool IsNewContextOK(Context newCtx) {
      return true;
    }

    public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink) {
      return new ForceGCObjectSink(nextSink, this);
    }
  }
308名無しさん♯:2001/05/25(金) 11:26

  class ForceGCObjectSink : IMessageSink
  {
    IMessageSink nextSink;
    ForceGCProperty prop;

    public ForceGCObjectSink(IMessageSink nextSink, ForceGCProperty prop) {
      this.nextSink = nextSink;
      this.prop = prop;
    }

    public IMessageSink NextSink {
      get { return nextSink; }
    }

    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) {
      return null;
    }

    public IMessage SyncProcessMessage(IMessage msg) {
      IMessage result = nextSink.SyncProcessMessage(msg);

      Console.WriteLine("--- GC ---");
      GC.Collect();

      return result;
    }
  }
}

// csc /t:library ForceGC.cs
309名無しさん♯:2001/05/25(金) 11:26
使用例。[ ForceGC ]をコメントアウトしてみて、違いを比べてちょ。


// Test.cs

using System;
using ForceGC;

// テストクラス。作成時と破棄時にメッセージを出すだけ。
class Hoge
{
  string name;

  public Hoge(string name) {
    this.name = name;
    Console.WriteLine("{0} Created.", name);
  }

  ~Hoge() {
    Console.WriteLine("{0} Destroyed.", name);
  }
}

[ ForceGC ]
class Container : ContextBoundObject
{
  public void Invoke1() {
    Hoge h1 = new Hoge("AAA");
    Hoge h2 = new Hoge("BBB");
  }  // ← ここでGC起動。

  public void Invoke2() {
    Hoge h3 = new Hoge("CCC");
  }  // ← ここでGC起動。
}

class EntryPoint
{
  public static void Main() {
    GC.RequestFinalizeOnShutdown();

    Container c = new Container();
    c.Invoke1();
    c.Invoke2();

    Hoge h4 = new Hoge("DDD");
  }
}

// csc /r:ForceGC.dll Test.cs
310名無しさん♯:2001/05/25(金) 11:32
一応言っておくけど、>>307-309 はお遊びレベルで作っただけで、
決して実用品じゃないからね。

だからツッコミは勘弁。
311304=306:2001/05/25(金) 13:36
>>307-310
うおお。ほんとにありがとうございます〜。
確かにガベコレが動いてる。不思議だ。。。