Jaa


每周源代码8

[原文发表地址]The Weekly Source Code 8

[原文发表时间] 2007-10-19 07:04 AM

沿袭我一贯的要求阅读源代码以开发出更好的程序,我将为大家呈上每周不限数系列“每周源代码”的第八篇,此后我也将继续附上其他的文章。这是我这周在读的我很欣赏的一些源代码。

Vista 电池节约装置是一个简单有趣的小应用,在你用电池运行时关闭Aero和工具条。源文件可以在CodePlex上找到。他在Windows上为电源通知注册了一个应用。Windows在系统电源状态转换时会给他的应用发出一个窗口消息。

    //In the main WinForm, he overrides the WndProc
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == PowerMngr.WM_POWERBROADCAST)
{
PowerMngr.GetManager().PowerSettingChange(m);
}
}

        //Earlier he selects the messages he's interested in.
internal void RegisterForPowerNotifications(IntPtr hwnd)
{
hPowerSrc = RegisterPowerSettingNotification(hwnd,
ref GUID_ACDC_POWER_SOURCE,
DEVICE_NOTIFY_WINDOW_HANDLE);

            hBattCapacity = RegisterPowerSettingNotification(hwnd,
ref GUID_BATTERY_PERCENTAGE_REMAINING,
DEVICE_NOTIFY_WINDOW_HANDLE);

            hMonitorOn = RegisterPowerSettingNotification(hwnd,
ref GUID_MONITOR_POWER_ON,
DEVICE_NOTIFY_WINDOW_HANDLE);

            hPowerScheme = RegisterPowerSettingNotification(hwnd,
ref GUID_POWERSCHEME_PERSONALITY,
DEVICE_NOTIFY_WINDOW_HANDLE);
}

        [DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(
IntPtr hRecipient,
ref Guid PowerSettingGuid,
Int32 Flags);

 

Patrick Smacchia今天发布了一款强类型路径库。大家都知道Patrick是一个独立思考的家伙,他很强大。他还加入了一个类图解:

clip_image002

我强烈建议你们去看下。我觉得一个这么聪敏的类会是BCL的一个很不错的附加。这里提供一些体现库用途的测试代码。注意Asserts中的!。在我看来,他们不是很明显,以通常使用的是==false。我觉得这个读起来很简单。

//

// Path string validation

//

string reason;

Debug.Assert(PathHelper.IsValidAbsolutePath(@"C:\Dir2\Dir1", out reason));

Debug.Assert(!PathHelper.IsValidAbsolutePath(@"C:\..\Dir1", out reason));

Debug.Assert(!PathHelper.IsValidAbsolutePath(@".\Dir1", out reason));

Debug.Assert(!PathHelper.IsValidAbsolutePath(@"1:\Dir1", out reason));

Debug.Assert(PathHelper.IsValidRelativePath(@".\Dir1\Dir2", out reason));

Debug.Assert(PathHelper.IsValidRelativePath(@"..\Dir1\Dir2", out reason));

Debug.Assert(PathHelper.IsValidRelativePath(@".\Dir1\..\Dir2", out reason));

Debug.Assert(!PathHelper.IsValidRelativePath(@".\Dir1\..\..\Dir2", out reason));

Debug.Assert(!PathHelper.IsValidRelativePath(@"C:\Dir1\Dir2", out reason));

 

这周我跟John Lam聊天时,他说:“顺便提一下,我对C# 3.0很有兴趣,这真的是一个很好的语言。我今天写了一个应用,把所有我们实践的Ruby方法都转储到了一个YAML文件。”这周晚些时候我会将它放到RubyForge上,这里先提供一部分片段。这有大概100行,阅读这些需要花些时间。这是一个简单且很好的方法来使用LINQ很简单,是也很好的方法来使用针对LINQ的反射,而且使用生成的扩展方法也很简洁方便。从底部的Main()方法开始读起,然后用你的方式看看。当然它可以更简短,不过这样做他好像是依照他自己的审美感去做到平衡。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Text;

using Ruby;

using Ruby.Extensions;

using Microsoft.Scripting.Utils;

using Ruby.Runtime;

namespace IronRuby.Library.Scanner {

static class ExtensionMethods {

public static IEnumerable<T> SelectCustomAttributes<T>(this Type type) where T : Attribute {

return type.GetCustomAttributes(typeof(T), false).Cast<T>();

}

        public static IEnumerable<T> SelectCustomAttributes<T>(this MethodInfo method) where T : Attribute {

return method.GetCustomAttributes(typeof(T), false).Cast<T>();

}

}

    class RubyClassInfo {

public Type ClrType { get; set; }

        public delegate void Block(IEnumerable<RubyMethodAttribute> methods);

        public string Name {

get { return ClrType.SelectCustomAttributes<RubyClassAttribute>().First().Name ?? ClrType.Name; }

}

        private Type LookupExtensionModuleType(IncludesAttribute attr) {

Type includedType;

Program.ExtensionModules.TryGetValue(attr.Type, out includedType);

return includedType ?? attr.Type;

}

        private void GetMethodNames(Type t, Block accumulate) {

var methods = (from m in t.GetMethods()

where m.IsDefined(typeof(RubyMethodAttribute), false)

select m.SelectCustomAttributes<RubyMethodAttribute>().First());

            accumulate(methods);

            foreach (IncludesAttribute attr in t.SelectCustomAttributes<IncludesAttribute>())

GetMethodNames(LookupExtensionModuleType(attr), accumulate);

}

        private IEnumerable<string> GetMethodNames(RubyMethodAttributes methodType) {

var result = new List<string>();

GetMethodNames(ClrType, methods =>

result.AddRange((from m in methods

where m.MethodAttributes == methodType

select m.Name).Distinct()));

result.Sort();

return result;

}

        public IEnumerable<string> InstanceMethods {

get { return GetMethodNames(RubyMethodAttributes.PublicInstance); }

}

        public IEnumerable<string> SingletonMethods {

get { return GetMethodNames(RubyMethodAttributes.PublicSingleton); }

}

}

    class Program {

static IEnumerable<RubyClassInfo> GetRubyTypes(Assembly a) {

return from rci in

(from t in a.GetTypes()

where t.IsDefined(typeof(RubyClassAttribute), false)

&& !t.IsDefined(typeof(RubyExtensionModuleAttribute), false)

select new RubyClassInfo { ClrType = t })

orderby rci.Name

select rci;

}

        static Dictionary<Type, Type> GetExtensionModules(Assembly a) {

var modules = from t in a.GetTypes()

where t.IsDefined(typeof(RubyExtensionModuleAttribute), false)

select new { Type = t, Attribute = t.SelectCustomAttributes<RubyExtensionModuleAttribute>().First() };

           

            var result = new Dictionary<Type, Type>();

foreach(var m in modules)

result[m.Attribute.Extends] = m.Type;

return result;

}

        const string RubyAssembly = @"Ruby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";

internal static Dictionary<Type, Type> ExtensionModules;

        static void DumpMethods(IEnumerable<RubyClassInfo> types, Func<RubyClassInfo, IEnumerable<string>> getMethods) {

foreach (RubyClassInfo rci in types) {

Console.WriteLine("{0}:", rci.Name);

foreach (string methodName in getMethods(rci))

Console.WriteLine(" - {0}", methodName);

}

}

        static void Main(string[] args) {

var name = new AssemblyName(RubyAssembly);

var a = Assembly.Load(name);

            ExtensionModules = GetExtensionModules(a);

var types = GetRubyTypes(a);

            DumpMethods(types, t => t.InstanceMethods);

DumpMethods(types, t => t.SingletonMethods);

}

}

}

 

如果找到任何很酷的阅读源代码的链接,请随时发给我。