ページ 11

C#のセッターについて

Posted: 2013年8月10日(土) 15:47
by たかたか
今、C#の勉強をしております。書籍を見ていてどうしても分からないところありますので、ご存知の方おりましたら教えて下さい。

setterのアクセス?の仕方についてです。
以下のようなクラスがあり、MediaOpendというプロパティが定義されています。
このプロパティに値をセットしている記述だと思われるのですが、
下の proxy.MediaOpend(proxy, new EventArgs()); という記述の仕方が分かりません。
プロパティを使った外部からの値のセット方法などは、色々なサイトで「proxy.MediaOpend = 値」のような書き方で紹介されています。
プロパティは、このようにメソッドの様なき方でもアクセスできるのでしょうか。
よろしくお願いいたします。

コード:

class TestMediaPlayerProxy: MusicPlayer.MediaPlayerProxy
{
...略...
internal EventHandler MediaOpend { get; set; }
}

var proxy = new TestMediaPlayerProxy();
proxy.MediaOpend(proxy, new EventArgs());

Re: C#のセッターについて

Posted: 2013年8月10日(土) 17:34
by eeeqqqwww
私が居るじゃない・・・

Re: C#のセッターについて

Posted: 2013年8月10日(土) 19:12
by ISLe
それはデリゲートによるメソッドの呼び出しです。

プロパティに対しては、デリゲートと同じシグネチャを持つメソッドをセットします。
メソッドがセットされていなければ呼び出しに失敗するので、どこか別の場所でメソッドをセットしているはずです。

Re: C#のセッターについて

Posted: 2013年8月10日(土) 21:48
by たかたか
ISLe様

 ご助言ありがとうございます!
 まだ自分のレベルでは理解するまでに時間がかかりそうですが、分からない部分を調べる糸口を知る事が出来ました。ありがとうございます。
デリゲードについて詳しく調べてみます。ちなみに、ちょっと長くて恐縮ですが以下が今回質問した内容に関係しそうなクラス定義部分になります。
よろしくお願いいたします。

コード:

namespace Lesson36
{
    public class MusicPlayer : IService
    {
        public class MediaPlayerProxy
        {
            public MediaPlayerProxy()
            {
                player = new MediaPlayer();
            }
            MediaPlayer player;
            public virtual void Open(Uri uri)
            {
                player.Dispatcher.Invoke(new Action(() => player.Open(uri)));
            }
            public virtual void Play()
            {
                player.Dispatcher.Invoke(new Action(() => player.Play()));
            }
            public virtual void Close()
            {
                player.Dispatcher.Invoke(new Action(() => player.Close()));
            }
            public virtual void AddMediaEnded(EventHandler hnd)
            {
                player.MediaEnded += hnd;
            }
            public virtual void AddMediaOpend(EventHandler hnd)
            {
                player.MediaOpened += hnd;
            }
        }
        public MusicPlayer(string path, MediaPlayerProxy proxy = null)
        {
            Directory = path;
            player = (proxy == null) ? new MediaPlayerProxy() : proxy;
            player.AddMediaOpend((o, e) =>
            {
                player.Play();
            });
            player.AddMediaEnded((o, e) =>
            {
                player.Close();
                lock (PlayList)
                {
                    PlayList.Dequeue();
                    if (PlayList.Count > 0)
                    {
                        player.Open(PlayList.Peek());
                    }
                }
            });
            PlayList = new Queue<Uri>();
        }
        MediaPlayerProxy player;
        /// <summary>
        /// プレイリスト。
        /// </summary>
        public Queue<Uri> PlayList { private set; get; }
        /// <summary>
        /// メディアファイルのルートディレクトリ。
        /// </summary>
        public string Directory { get; set; }
        static readonly Regex MusicFiles = new Regex(@"(wma|mp3|m4a)\Z", RegexOptions.IgnoreCase);
        public void service(string path, HttpListenerRequest request, System.Net.HttpListenerResponse response)
        {
            var prefix = string.Empty;
            var dir = string.Empty;
            path = WebUtility.UrlDecode(path);
            var pathbegin = path.IndexOf('/');
            if (pathbegin >= 0 && pathbegin < path.Length - 1)
            {
                dir = path.Substring(pathbegin + 1).Replace('/', Path.DirectorySeparatorChar);
            }
            var file = new FileInfo(Path.Combine(Directory, dir));
            if (!file.Exists && !new DirectoryInfo(file.FullName).Exists)
            {
                response.StatusCode = 404;
                return;
            }
            if ((file.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
            {
                dir = file.DirectoryName;
                AddMusicToList(new Uri(file.FullName));
            }
            else
            {
                if (path.Last() != '/')
                {
                    prefix = path.Substring(path.LastIndexOf('/') + 1) + "/";
                }
            }
            using (var writer = new StreamWriter(response.OutputStream, Encoding.UTF8))
            {
                WriteHtml(prefix, dir, writer);
            }
        }
        /// <summary>
        /// 指定したUriをプレイリストに追加する。
        /// もし、現在再生中でなければ再生を開始する。
        /// </summary>
        /// <param name="uri">再生対象のファイルのURI</param>
        public void AddMusicToList(Uri uri)
        {
            lock (PlayList)
            {
                PlayList.Enqueue(uri);
                if (PlayList.Count == 1)
                {
                    player.Open(uri);
                }
            }
        }
        /// <summary>
        /// 指定したTextWriterへHTMLを出力する。
        /// </summary>
        /// <param name="prefix">ファイル名に付加するパス名</param>
        /// <param name="path">仮想ディレクトリ名(セパレータはプラットフォーム規定)</param>
        /// <param name="writer">出力先のTextWriter</param>
        public void WriteHtml(string prefix, string path, TextWriter writer)
        {
            var dir = Path.Combine(Directory, path);
            writer.Write(@"<!DOCUMENT html>
<html>
<head>
</head>
<body>
<ul>
");
            if (path.Length > 0)
            {
                writer.Write("<li><a href=\"" + ((prefix.Length == 0) ? "../" : string.Empty) + "\">[..]</a>");
            }
            writer.Write(string.Join("\r\n",
                System.IO.Directory.EnumerateDirectories(dir)
                    .Select((nm) => new DirectoryInfo(nm).Name.ToLower())
                    .Select((nm) => "<li><a href=\"" + prefix + nm + "/\">[" + nm + "]</a></li>")));
            writer.Write(string.Join("\r\n",
                System.IO.Directory.EnumerateFiles(dir)
                    .Select((nm) => new FileInfo(nm))
                    .Where((fi) => MusicFiles.IsMatch(fi.Extension))
                    .Select((fi) => "<li><a href=\"" + prefix + fi.Name.ToLower() + "\">" + fi.Name.ToLower() + "</a></li>")));
            writer.Write(@"</ul>
<ul>Playing:
");
            lock (PlayList)
            {
                writer.Write(string.Join("\r\n", PlayList.Select(uri => "<li>" + new FileInfo(uri.LocalPath).Name + "</li>")));
            }
            writer.Write(@"</ul>
</body>
</html>");
        }
    }
}
--------------------------------

コード:

namespace Lesson36Test
{
    [TestClass]
    public class UnitTest1
    {
        static readonly string TestDirectory = Path.Combine(Path.GetTempPath(), "__Lesson36Test__");
        static readonly string ChildDir = Path.Combine(TestDirectory, "1");
        [TestInitialize]
        public void SetUp()
        {
            Directory.CreateDirectory(TestDirectory);
            File.Create(Path.Combine(TestDirectory, "1.wma")).Close();
            File.Create(Path.Combine(TestDirectory, "2.WMA")).Close();
            Directory.CreateDirectory(ChildDir);
            File.Create(Path.Combine(ChildDir, "10.wma")).Close();
            File.Create(Path.Combine(ChildDir, "20.wma")).Close();
        }
        [TestCleanup]
        public void TearDown()
        {
            Directory.Delete(TestDirectory, true);
        }
        [TestMethod]
        public void TestHtml()
        {
            var player = new MusicPlayer(TestDirectory);
            var writer = new StringWriter();
            player.WriteHtml(string.Empty, string.Empty, writer);
            var result = writer.ToString();
            Assert.IsTrue(result.IndexOf("<a href=\"1.wma\">1.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"2.wma\">2.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"1/\">[1]</a>") >= 0);
            Assert.IsFalse(result.IndexOf("[..]") >= 0);
        }
        [TestMethod]
        public void TestNavigate()
        {
            var player = new MusicPlayer(TestDirectory);
            var writer = new StringWriter();
            player.WriteHtml("1/", "1", writer);
            var result = writer.ToString();
            Assert.IsTrue(result.IndexOf("<a href=\"1/10.wma\">10.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"1/20.wma\">20.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"\">[..]</a>") >= 0);
            writer = new StringWriter();
            player.WriteHtml("", "1", writer);
            result = writer.ToString();
            Assert.IsTrue(result.IndexOf("<a href=\"10.wma\">10.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"20.wma\">20.wma</a>") >= 0);
            Assert.IsTrue(result.IndexOf("<a href=\"../\">[..]</a>") >= 0);
        }

        class TestMediaPlayerProxy : MusicPlayer.MediaPlayerProxy
        {
            internal TestMediaPlayerProxy()
            {
            }
            void CallAction(Action action)
            {
                if (action != null)
                {
                    action();
                }
            }
            internal Uri CurrentUri { get; set; }
            internal Action OpenAction { get; set; }
            public override void Open(Uri uri)
            {
                CurrentUri = uri;
                CallAction(OpenAction);
            }
            internal bool IsPlaying { get; set; }
            internal Action PlayAction { get; set; }
            public override void Play()
            {
                IsPlaying = true;
                CallAction(PlayAction);
            }
            internal Action CloseAction { get; set; }
            public override void Close()
            {
                CallAction(CloseAction);
            }
            internal EventHandler MediaOpend { get; set; }
            public override void AddMediaOpend(EventHandler hnd)
            {
                MediaOpend = hnd;
            }
            internal EventHandler MediaEnded { get; set; }
            public override void AddMediaEnded(EventHandler hnd)
            {
                MediaEnded = hnd;
            }
        }
        [TestMethod]
        public void TestPlay()
        {
            var proxy = new TestMediaPlayerProxy();
            var player = new MusicPlayer(TestDirectory, proxy);
            Assert.IsNull(proxy.CurrentUri);
            var uri = new Uri(Path.Combine(TestDirectory, "1.wma"));
            player.AddMusicToList(uri);
            Assert.AreEqual(uri, proxy.CurrentUri);
            Assert.IsFalse(proxy.IsPlaying);
            proxy.MediaOpend(proxy, new EventArgs());
            Assert.IsTrue(proxy.IsPlaying);
            Assert.AreEqual(1, player.PlayList.Count);
            proxy.MediaEnded(proxy, new EventArgs());
            Assert.AreEqual(0, player.PlayList.Count);
        }
        [TestMethod]
        public void TestRemoveList()
        {
            var proxy = new TestMediaPlayerProxy();
            var player = new MusicPlayer(TestDirectory, proxy);
            var uriFirst = new Uri(Path.Combine(TestDirectory, "1.wma"));
            var uriSecond = new Uri(Path.Combine(TestDirectory, "2.wma"));
            player.PlayList.Enqueue(uriFirst);
            player.PlayList.Enqueue(uriSecond);
            Assert.AreEqual(2, player.PlayList.Count);
            Assert.AreEqual(uriFirst, player.PlayList.Peek());
            proxy.MediaEnded(proxy, new EventArgs());
            Assert.AreEqual(1, player.PlayList.Count);
            Assert.AreEqual(uriSecond, player.PlayList.Peek());
        }
        [TestMethod]
        public void TestLock()
        {
            var proxy = new TestMediaPlayerProxy();
            var player = new MusicPlayer(TestDirectory, proxy);
            var uriFirst = new Uri(Path.Combine(TestDirectory, "1.wma"));
            var uriSecond = new Uri(Path.Combine(TestDirectory, "2.wma"));
            player.PlayList.Enqueue(uriFirst);
            player.PlayList.Enqueue(uriSecond);
            var openWasCalled = false;
            proxy.OpenAction = () =>
            {
                Assert.AreEqual(uriSecond, proxy.CurrentUri);
                Assert.IsTrue(Monitor.IsEntered(player.PlayList));
                openWasCalled = true;
            };
            proxy.MediaEnded(proxy, new EventArgs());
            Assert.IsTrue(openWasCalled);
        }
    }
}

Re: C#のセッターについて

Posted: 2013年8月10日(土) 22:03
by ISLe
AddMediaOpendメソッドの中でプロパティを使っていますね。

Re: C#のセッターについて

Posted: 2013年8月10日(土) 23:41
by たかたか
ISLe様

 ありがとうございます!何となく見方が分かった気がします。
イベントデリゲートというものをAddMediaOpendメソッドの中でsetterに渡しているので、
自分が質問したproxy.MediaOpend の呼び出しはsetterではなく、getterの動きなんですね。
proxy.MediaOpendでイベントデリゲートを実行する流れになるのですね。
C#難しいです。この辺の仕組み勉強します。ありがとうございました。