partial classes(局部类型)

partial classes的定义

     c#2.0引入了局部类型的概念。局部类型允许我们将一个类、接口或结构分成好几个部分,分别实现在几个不同的.cs文件中。

局部类型适用于以下情况:  

(1)类型特别大,不宜放在一个文件中实现。  

(2)一个类型中的一部分代码为自动化工具生成的代码,不宜与我们自己编写的代码混合在一起。  

(3)需要多人合作编写一个类。

    

局部类型的限制

 (1)局部类型只适用于类、接口、结构,不支持委托和枚举。  

 (2)同一个类型的各个部分必须都有修饰符partial。 

 (3)使用局部类型时,一个类型的各个部分必须位于相同的命名空间中。 

 (4)一个类型的各个部分必须同时编译。

局部类型的注意点

    (1)关键字partial是一个上下文关键字,只有和class、struct、interface放在一起时才有关键字的含义。因此partial得引入不会影响现有代码中名称为partial的变量。   

    (2)局部类型的各个部分一般是分开放在几个不同的.cs文件中,但c#编译器允许我们呢将他们放在同一文件中。

应用举例

    public static partial class ImageListViewRenderers
    {
        #region DefaultRenderer
        /// <summary>
        /// The default renderer.
        /// </summary>
        public class DefaultRenderer : ImageListView.ImageListViewRenderer
        {
            /// <summary>
            /// Initializes a new instance of the DefaultRenderer class.
            /// </summary>
            public DefaultRenderer()
            {
                ;
            }
        }

        #endregion

   }


    /// <summary>
    /// Represents the built-in renderers.
    /// </summary>
    public static partial class ImageListViewRenderers
    {
        #region NewYear2010Renderer
        /// <summary>
        /// A renderer to celebrate the new year of 2010.
        /// </summary>
        /// <remarks>Compile with conditional compilation symbol BONUSPACK to
        /// include this renderer in the assembly.</remarks>
        public class NewYear2010Renderer : ImageListView.ImageListViewRenderer
        {
            /// <summary>
            /// Represents a snow flake
            /// </summary>
            private class SnowFlake
            {
                /// <summary>
                /// Gets or sets the client coordinates of the snow flake.
                /// </summary>
                public Point Location { get; set; }
                /// <summary>
                /// Gets or sets the rotation angle of the snow flake in degrees.
                /// </summary>
                public double Rotation { get; set; }
                /// <summary>
                /// Gets or sets the size of the snow flake.
                /// </summary>
                public int Size { get; set; }

                /// <summary>
                /// Initializes a new instance of the SnowFlake class.
                /// </summary>
                /// <param name="newSize">The size of the snow flake.</param>
                public SnowFlake(int newSize)
                {
                    Size = newSize;
                    Location = new Point(0, 0);
                    Rotation = 0.0;
                }
            }

            private readonly object lockObject = new object();

            private int maxFlakeCount = 100;
            private int minFlakeSize = 4;
            private int maxFlakeSize = 12;
            private int flakeGeneration = 3;
            private int currentGeneration = 0;
            private long refreshPeriod = 50;
            private int fallSpeed = 3;
            private DateTime lastRedraw = DateTime.Now;
            private volatile bool inTimer = false;

            private List<SnowFlake> flakes = null;
            private System.Threading.Timer timer;
            private Random random = new Random();

            private Rectangle displayBounds = Rectangle.Empty;

            private GraphicsPath flake;
            private GraphicsPath terrain;

            /// <summary>
            /// Initializes a new instance of the NewYear2010Renderer class.
            /// </summary>
            public NewYear2010Renderer()
            {
                flake = CreateFlake(10, 3);
                terrain = CreateTerrain();
                timer = new System.Threading.Timer(UpdateTimerCallback, null, 0, refreshPeriod);
            }

            /// <summary>
            /// Generates a snowflake from a Koch curve.
            /// http://en.wikipedia.org/wiki/Koch_snowflake
            /// </summary>
            /// <param name="size">The size of the snow flake.</param>
            /// <param name="iterations">Number of iterations. Higher values
            /// produce more complex curves.</param>
            private GraphicsPath CreateFlake(int size, int iterations)
            {
                Queue<PointF> segments = new Queue<PointF>();
                float h = (float)Math.Sin(Math.PI / 3.0) * (float)size;
                PointF v1 = new PointF(-1.0f * (float)size / 2.0f, -h / 3.0f);
                PointF v2 = new PointF((float)size / 2f, -h / 3.0f);
                PointF v3 = new PointF(0.0f, h * 2.0f / 3.0f);
                segments.Enqueue(v1); segments.Enqueue(v2);
                segments.Enqueue(v2); segments.Enqueue(v3);
                segments.Enqueue(v3); segments.Enqueue(v1);

                for (int k = 0; k < iterations - 1; k++)
                {
                    int todivide = segments.Count / 2;
                    for (int i = 0; i < todivide; i++)
                    {
                        PointF p1 = segments.Dequeue();
                        PointF p2 = segments.Dequeue();

                        // Trisect the segment
                        PointF pi1 = new PointF((p2.X - p1.X) / 3.0f + p1.X,
                            (p2.Y - p1.Y) / 3.0f + p1.Y);
                        PointF pi2 = new PointF((p2.X - p1.X) * 2.0f / 3.0f + p1.X,
                            (p2.Y - p1.Y) * 2.0f / 3.0f + p1.Y);
                        double dist = Math.Sqrt((pi1.X - pi2.X) * (pi1.X - pi2.X) + (pi1.Y - pi2.Y) * (pi1.Y - pi2.Y));
                        double angle = Math.Atan2(p2.Y - p1.Y, p2.X - p1.X) - Math.PI / 3.0;
                        PointF pn = new PointF(pi1.X + (float)(Math.Cos(angle) * dist),
                            pi1.Y + (float)(Math.Sin(angle) * dist));

                        segments.Enqueue(p1); segments.Enqueue(pi1);
                        segments.Enqueue(pi1); segments.Enqueue(pn);
                        segments.Enqueue(pn); segments.Enqueue(pi2);
                        segments.Enqueue(pi2); segments.Enqueue(p2);
                    }
                }

                GraphicsPath path = new GraphicsPath();
                while (segments.Count != 0)
                {
                    PointF p1 = segments.Dequeue();
                    PointF p2 = segments.Dequeue();
                    path.AddLine(p1, p2);
                }

                path.CloseFigure();
                return path;
            }

            /// <summary>
            /// Generates a random snowy terrain.
            /// </summary>
            private GraphicsPath CreateTerrain()
            {
                Random rnd = new Random();
                GraphicsPath path = new GraphicsPath();
                int width = 100;
                int height = 10;

                int count = 20;
                int step = width / count;
                int lastx = 0, lasty = 0;
                Point[] points = new Point[count];
                for (int i = 0; i < count; i++)
                {
                    int x = i * (width + 2 * step) / count - step;
                    int y = rnd.Next(-height / 2, height / 2);
                    points[i] = new Point(x, y);
                    lastx = x;
                    lasty = y;
                }
                path.AddCurve(points);

                path.AddLine(lastx, lasty, width + step, 0);
                path.AddLine(width + step, 0, width + step, 200);
                path.AddLine(width + step, 200, -step, 200);
                path.CloseFigure();

                return path;
            }

            /// <summary>
            /// Updates snow flakes at each timer tick.
            /// </summary>
            /// <param name="state">Not used, null.</param>
            private void UpdateTimerCallback(object state)
            {
                if (inTimer) return;
                inTimer = true;

                bool redraw = false;

                lock (lockObject)
                {
                    if (displayBounds.IsEmpty)
                    {
                        inTimer = false;
                        return;
                    }

                    if (flakes == null)
                        flakes = new List<SnowFlake>();

                    // Add new snow flakes
                    currentGeneration++;
                    if (currentGeneration == flakeGeneration)
                    {
                        currentGeneration = 0;
                        if (flakes.Count < maxFlakeCount)
                        {
                            SnowFlake snowFlake = new SnowFlake(random.Next(minFlakeSize, maxFlakeSize));
                            snowFlake.Rotation = 360.0 * random.NextDouble();
                            snowFlake.Location = new Point(random.Next(displayBounds.Left, displayBounds.Right), -20);
                            flakes.Add(snowFlake);
                        }
                    }

                    // Move snow flakes
                    for (int i = flakes.Count - 1; i >= 0; i--)
                    {
                        SnowFlake snowFlake = flakes[i];
                        if (snowFlake.Location.Y > displayBounds.Height)
                            flakes.Remove(snowFlake);
                        else
                        {
                            snowFlake.Location = new Point(snowFlake.Location.X, snowFlake.Location.Y + snowFlake.Size * fallSpeed / 10);
                            snowFlake.Rotation += 360.0 / 40.0;
                            if (snowFlake.Rotation > 360.0) snowFlake.Rotation -= 360.0;
                        }
                    }

                    // Do we need a refresh?
                    if ((DateTime.Now - lastRedraw).Milliseconds > refreshPeriod)
                        redraw = true;
                }

                if (redraw)
                {
                    try
                    {
                        if (ImageListView.InvokeRequired)
                            ImageListView.Invoke((MethodInvoker)delegate { ImageListView.Refresh(); });
                        else
                            ImageListView.Refresh();
                    }
                    catch
                    {
                        ;
                    }
                }

                inTimer = false;
            }

            /// <summary>
            /// Initializes the System.Drawing.Graphics used to draw
            /// control elements.
            /// </summary>
            /// <param name="g">The System.Drawing.Graphics to draw on.</param>
            public override void InitializeGraphics(Graphics g)
            {
                base.InitializeGraphics(g);
                g.SmoothingMode = SmoothingMode.HighQuality;
            }

            /// <summary>
            /// Sets the layout of the control.
            /// </summary>
            /// <param name="e">A LayoutEventArgs that contains event data.</param>
            public override void OnLayout(LayoutEventArgs e)
            {
                base.OnLayout(e);
                lock (lockObject)
                {
                    displayBounds = ImageListView.DisplayRectangle;
                }
            }

            /// <summary>
            /// Draws an overlay image over the client area.
            /// </summary>
            /// <param name="g">The System.Drawing.Graphics to draw on.</param>
            /// <param name="bounds">The bounding rectangle of the client area.</param>
            public override void DrawOverlay(Graphics g, Rectangle bounds)
            {
                lock (lockObject)
                {
                    lastRedraw = DateTime.Now;
                }

                // Draw the terrain
                DrawTerrain(g);

                lock (lockObject)
                {
                    // Draw the snow flakes
                    if (flakes != null)
                    {
                        foreach (SnowFlake snowFlake in flakes)
                            DrawSnowFlake(g, snowFlake);
                    }
                }

                // Redraw some of the terrain over slow flakes
                DrawTerrainOutline(g);
            }

            /// <summary>
            /// Draws a snow flake.
            /// </summary>
            /// <param name="g">The System.Drawing.Graphics to draw on.</param>
            /// <param name="snowFlake">The snowflake to draw.</param>
            private void DrawSnowFlake(Graphics g, SnowFlake snowFlake)
            {
                g.ResetTransform();
                // Tranform to upper left corner before rotating.
                // This produces a nice wobbling effect.
                g.TranslateTransform(-snowFlake.Size / 2, -snowFlake.Size / 2, MatrixOrder.Append);
                g.ScaleTransform((float)snowFlake.Size / 6.0f, (float)snowFlake.Size / 6.0f);
                g.RotateTransform((float)snowFlake.Rotation, MatrixOrder.Append);
                g.TranslateTransform(snowFlake.Location.X, snowFlake.Location.Y, MatrixOrder.Append);
                using (SolidBrush brush = new SolidBrush(Color.White))
                using (Pen pen = new Pen(Color.Gray))
                using (Pen glowPen = new Pen(Color.FromArgb(96, Color.White), 2.0f))
                {
                    g.DrawPath(glowPen, flake);
                    g.FillPath(brush, flake);
                    g.DrawPath(pen, flake);
                }

                g.ResetTransform();
            }

            /// <summary>
            /// Draws the terrain.
            /// </summary>
            /// <param name="g">The System.Drawing.Graphics to draw on.</param>
            private void DrawTerrain(Graphics g)
            {
                g.ResetTransform();
                using (SolidBrush brush = new SolidBrush(Color.White))
                using (Pen pen = new Pen(Color.Gray))
                {
                    Rectangle rec = ImageListView.DisplayRectangle;
                    g.ScaleTransform((float)rec.Width / 100.0f, 3.0f, MatrixOrder.Append);
                    g.TranslateTransform(0, rec.Height - 30, MatrixOrder.Append);
                    g.FillPath(brush, terrain);
                    g.DrawPath(pen, terrain);
                }
                g.ResetTransform();
            }

            /// <summary>
            /// Draws the terrain outline.
            /// </summary>
            /// <param name="g">The System.Drawing.Graphics to draw on.</param>
            private void DrawTerrainOutline(Graphics g)
            {
                g.ResetTransform();
                using (SolidBrush brush = new SolidBrush(Color.White))
                {
                    Rectangle rec = ImageListView.DisplayRectangle;
                    g.ScaleTransform((float)rec.Width / 100.0f, 3.0f, MatrixOrder.Append);
                    g.TranslateTransform(0, rec.Height - 20, MatrixOrder.Append);
                    g.FillPath(brush, terrain);
                }
                g.ResetTransform();
            }

            /// <summary>
            /// Releases managed resources.
            /// </summary>
            public override void Dispose()
            {
                base.Dispose();

                flake.Dispose();
                terrain.Dispose();
                timer.Dispose();
            }
        }
        #endregion
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值