OAuth2学习及DotNetOpenAuth部分源码研究

发布时间 : 星期二 文章OAuth2学习及DotNetOpenAuth部分源码研究更新完毕开始阅读

gePartEncoder, out encoder)) { encoder = encoders[messagePartEncoder] = (IMessagePartEncoder)Activator.CreateInstance(messagePartEncoder); } } return encoder; } }

ValueMapping类负责某对象与字符串之间的转换.converters字段缓存了各类型与ValueMapping之间的对应关系.在此对象首次加载时就会通过调用Map方法自动注册常见类型的转换方式.而构造函数则会从特性中或是从缓存中尝试获取ValueMapping. internalstruct ValueMapping { internalreadonly Func ValueToString; internalreadonly Func StringToValue; internal ValueMapping(Func toString, Func toOriginalString, Func toValue) : this() { this.ValueToString = toString; this.StringToValue = toValue; } internal ValueMapping(IMessagePartEncoder encoder) : this() { this.ValueToString = obj => (obj != null) ? encoder.Encode(obj) : nullString; this.StringToValue = str => (str != null) ? encoder.Decode(str) : null; } }

这里定义了两个委托,分别负责对象到字符串和字符串到对象的转换.如果传入一个IMessagePartEncoder类型,则将功能委托给此类型执行.

publicinterface IMessagePartEncoder { string Encode(object value); object Decode(string value); }

由于MessagePartAttribute特性拥有IMessagePartEncoder属性,这为自定义序列化转换提供了可能.比如上文曾说的各类令牌的基类AuthorizationDataBag

publicabstractclass AuthorizationDataBag : DataBag, IAuthorizationDescription { [MessagePart(Encoder = typeof(ScopeEncoder))] public HashSet Scope { get; privateset; } }

由于系统未定义从HashSet到字符串之间的转换,所以需要在标记特性时告知映射类ScopeEncoder

internalclass ScopeEncoder : IMessagePartEncoder { publicstring Encode(object value) { var scopes = (IEnumerable)value; return (scopes != null&& scopes.Any()) ? string.Join(\, scopes.ToArray()) : null; } publicobject Decode(string value) { return OAuthUtilities.SplitScopes(value); } } publicstaticclass OAuthUtilities { publicstatic HashSet SplitScopes(string scope) {varset = new HashSet(scope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries), ScopeStringComparer);returnset; } }

可以看到,其实就是HashSet各项用逗号拼接.

上面获取的映射器最终会在取值或赋值时使用,下面这些赋值或取值的语法非常像.Net中反射的语法.

internalclass MessagePart { internalstring GetValue(IMessage message) { object value = this.GetValueAsObject(message); returnthis.ToString(value, false); } privatestring ToString(object value, bool originalString) { return originalString ? this.converter.ValueToOriginalString(value) : this.converter.

ValueToString(value); } internalvoid SetValue(IMessage message, string value) { this.SetValueAsObject(message, this.ToValue(value)); } privatevoid SetValueAsObject(IMessage message, object value) { if (this.property != null) { this.property.SetValue(message, value, null); } else { this.field.SetValue(message, value); } } privateobject ToValue(string value) { returnthis.converter.StringToValue(value); } }

MessageDescription对象用来描述对象

internalclass MessageDescription { private Dictionary mapping; internal MessageDescription(Type messageType, Version messageVersion) { this.MessageType = messageType; this.MessageVersion = messageVersion; this.ReflectMessageType(); } privatevoid ReflectMessageType() { this.mapping = new Dictionary(); Type currentType = this.MessageType; do { foreach (MemberInfo member in currentType.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) { if (member is PropertyInfo || member is FieldInfo) { MessagePartAttribute partAttribute = (from a in member.GetCustomAttributes(typeof(MessagePartAttribute), true).OfType() orderby a.MinVersionValue descending where a.MinVersionValue <= this.MessageVersion where a.MaxVersionValue >= this.MessageVersion select a).FirstOrDefault(); if (partAttribute != null) { MessagePart part = new MessagePart(member, partAttribute); if (this.

mapping.ContainsKey(part.Name)) { Logger.Messaging.WarnFormat( \ message part named {1}. Inherited members will be hidden.\, this.MessageType.Name, part.Name); } else { this.mapping.Add(part.Name, part); } } } } currentType = currentType.BaseType; } while (currentType != null); BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; this.Constructors = this.MessageType.GetConstructors(flags); } }

可以看到,此结象每一个实例都用来描述一个类,在初始化时会调用ReflectMessageType方法.此方法会反射并遍例所有类成员,并将标记了MessagePartAttribute特性的成员对成对应的MessagePart描述类并记录在对象内部的Dictionary类型字典中.

为了提高性能,作者引入了MessageDescriptionCollection类

internalclass MessageDescriptionCollection : IEnumerable { privatereadonly Dictionary reflectedMessageTypes = new Dictionary(); internal MessageDescription Get(Type messageType, Version messageVersion) { MessageTypeAndVersion key = new MessageTypeAndVersion(messageType, messageVersion); MessageDescription result; lock (this.reflectedMessageTypes) { this.reflectedMessageTypes.TryGetValue(key, out result); } if (result == null) { // Construct the message outside the lock.var newDescription = new MessageDescription(messageType, messageVersion); // Then use the lock again to either acquire what someone else has created in the meantime, or // set and use our own result.lock (this.reflectedMessageTypes) { if (!this.reflectedMessageTypes.TryGetValue(key, out result)) { this.reflectedMessageTypes[ke

联系合同范文客服:xxxxx#qq.com(#替换为@)