利用dot Net技术中反射及代码发送的
动态退化或同步化接口封装
1 技术背景
在“动态”这个词到处用的时代,怎样能够让程序真正的动态起来。
在Java的结构中我们看到了一个java.lang.reflect包,开始让程序能够了解程序的结构。然后作为Java的好徒弟dot Net框架中System.Reflection命名空间看到了 AssemblyBuilder,ModuleBuilder,TypeBuilder及其它*Builder,而程序能够构造程序结构。我们进入了真正的动态运用的时代。
回想一下,这是多么令人震惊的功能啊!让我们运行动态生成的代码吧。如果你运行的不是原本硬盘上载入的代码,那是多大的飞跃啊!
1.1 反射
反射是dot Net框架中的面向对象技术中的一个极为重要的部分。它由System.Type类和System.Reflection命名空间及其子空间中的所有类完成。在所有类的根类Object的实例方法GetType()可以得到描述实例的类信息的Type类实例。
反射的功能使得程序可以了解自身结构的手段,除此还可以提供动态构造程序集(Assembly),模块(Module),类(Type)结构的途径,使得原本僵死的程序有了活力。反射使得程序可以访问程序结构,构造程序结构。反射(reflection也称retrospection)的还可翻译为“自省”或“反省” 。
1.2 代码发送
代码发送就是运行时向方法构造器发送操作码和参数,使得最终实现动态生成类。然后就可以使用需要的代码结构进行操作。
反射发送是一种“发送”操作码的强大技术。虽然今天的编译器速度很快,内存和处理器的速度也足够,但是在必须的时候能够触及这么核心底层的部分,确实是一件令人欣慰的事情。
2 退化与同步化理论
2.1 退化
由面向对象的继承性多态性使得编程模型呈现出一个扩展的发散的结构,在许多接口的应用中将会只用到部分的功能(这里一般指方法(Method),dot Net中还包括属性(Property)和事件(Event))。那么对于其他的部分只好在实现时放出异常或不作任何操作。如此便出现了退化,也就是一部分功能的退化。举例来讲:
l Sysetm.Collections.IList的C#语言声明:
public interface IList : ICollection, IEnumerable
{
int Add(object value);
void Clear();
bool Contains(object value);
int IndexOf(object value);
void Insert(int index, object value);
void Remove(object value);
void RemoveAt(int index);
bool IsFixedSize { get; }
bool IsReadOnly { get; }
object this[int index] { get; set; }
}
要实现上面的IList接口的只读(Read Only)封装是,要求在一个只读的派生类中退化Add, Clear, Insert, Remove, RemoveAt, this[]{set;}这些方法或属性,并且IsReadOnly返回常量true。 然而如此只是文档的规则不能保证一个返回IsReadOnly 为true的实例必然做好了ReadOnly退化。
这样的退化仅仅是文档内的约定,而更应该程序约束。在后面的动态封装中就介绍了标准的退化封装的手段。
2.2 同步化
实现同步化封装一般对要封装的类或接口的所有方法重写,重写模版如下:
public override ReturnType A_Method()
{
lock (this._syncRoot)
return this._target.A_Method();
}
在直接调用前后,要进行同步化操作进入对象和退出对象。这样实现的类就成为原有类或接口的同步化封装。由于在多线程的应用中经常用到同步化封装,这里不赘述其应用了。
3 dot Net 框架中的退化与同步化封装实现
ReadOnlyList类是Sysetm.Collections.ArrayList类的私有嵌套类,是对IList接口的ReadOnly退化封装。
SyncList类是Sysetm.Collections.ArrayList类的私有嵌套类,是对IList接口的同步化封装。
通过的两个静态方法可以获得相应的封装实例,下面是相关的部分C#声明:
l ArrayList类的摘要声明:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
{
……
private class ReadOnlyList : IList
{……}
private class SyncIList : IList
{……}
public static IList ReadOnly(IList list)
{
if (list == null)
throw new ArgumentNullException("list");
return new ArrayList. ReadOnlyList(list);
}
public static IList Synchronized(IList list)
{
if (list == null)
throw new ArgumentNullException("list");
return new ArrayList.SyncIList(list);
}
}
l ReadOnlyList类的摘要声明:
private class ReadOnlyList : IList
{
internal ReadOnlyList(IList l)
{
this._list = l;
}
private IList _list;
//退化方法实现
public virtual int Add(object obj)
{
throw new NotSupportedException(Environment.GetResourceString("NotSupported"));
}
……
//非退化方法实现
public virtual bool Contains(object obj)
{
return this._list.Contains(obj);
}
……
public virtual bool IsReadOnly
{
get
{
return true;
}
}
……
}
退化的方法例如Add,放出异常。非退化的方法例如Contains,直接调用。只有IsReadOnly特殊处理返回true。
l SyncList类的摘要声明:
private class SyncIList : IList
{
internal SyncIList(IList list)
{
this._list = list;
this._root = list.SyncRoot;
}
private IList _list;
private object _root;
public virtual int Add(object value)
{
lock (this._root)
return this._list.Add(value);
}
……
public virtual bool IsSynchronized
{
get
{
return true;
}
}
……
public virtual object SyncRoot
{
get
{
return this._root;
}
}
}
同步化处理所有方法例如Add。只有IsSynchronized特殊处理返回true,SyncRoot特殊处理返回初始化时输入的异步根。
4 动态封装模型
4.1 原有模式的弊端
由上面dot Net框架里的实现方法可以看到,针对需要封装的接口要写出对应的类实现。也就是说每次要按照退化或同步化的模式编写代码。可以看到代码的信息量如此之小,可以说,编写这样的代码是程序员的悲哀。
程序员的第一原则,所有重复的操作要让程序去做。如果程序员手动去做这件事不仅是折磨程序员,而且是摧毁了程序的严谨结构。这样,差错容易出现,程序可读性降低,代码冗余繁杂。
于是按照上面的模式而生成的类应该由程序实现,有人会用文本处理自动生成代码,但这不是我们的最终目的。我们要的只是一个继承对应接口的类结构,而且对具体的类名称不敏感,但我们需要他全局唯一,从而在下次引用方便。所以如果靠生成代码,那么他就不能作为通用的标准在标准库中创建实例。
客观的讲,任何地方声明的接口,都应有其唯一对应的封装实现。而不是由不同的程序员去一次次的编写不同的实现,这样也不能给出标准封装检查。
4.2 理想的封装模型
l 全局封装器Boxer类的C#语言封装部分声明:
public sealed class Boxer
{
public static object Degenerate(object target, Type interfaceType, IDegenerateProvider dp);
public static object Degenerate(object target, Type interfaceType, Type degenerateAttributeType);
public static object Synchronize(object target, Type interfaceType);
public static object Synchronize(object target, Type interfaceType, object syncRoot);
……
}
我们可以通过前两个的静态方法获得任意接口的指定退化方式的退化实例。也可通过后两个静态方法获得任意接口的异步封装。
l IDegenerateProvider接口的C#语言完整声明:
public interface IDegenerateProvider
{
DegenerateTargets NeedDegenerate(EventInfo evn);
bool NeedDegenerate(MethodInfo method);
DegenerateTargets NeedDegenerate(PropertyInfo property);
}
提供判断是否退化的判断方法的接口。退化需要提供这样的供应器实例。
l Boxer类的C#语言封装检查部分声明:
public sealed class Boxer
{
public static bool IsDegenerated(object target, IDegenerateProvider dp);
public static bool IsDegenerated(object target, Type degenerateAttributeType);
public static bool IsDegenerated(object target, Type interfaceType, IDegenerateProvider dp);
public static bool IsDegenerated(object target, Type interfaceType, Type degenerateAttributeType);
public static bool IsSynchronized(object target);
public static bool IsSynchronized(object target, object syncRoot);
public static bool IsSynchronized(object target, Type interfaceType);
public static bool IsSynchronized(object target, Type interfaceType, object syncRoot);
……
}
l DegenerateAttribute属性类和DegenerateTargets枚举类的C#语言完整声明:
public abstract class DegenerateAttribute : Attribute
{
protected DegenerateAttribute(): this(DegenerateTargets.All){}
protected DegenerateAttribute(DegenerateTargets targets)
{
this._targets = targets;
}
public DegenerateTargets Targets { get{ return this._targets;} }
private readonly DegenerateTargets _targets;
public static IDegenerateProvider GetDegenerateProvider(Type attributeType);
internal class DegenerateProvider : IDegenerateProvider
{
public DegenerateProvider(Type attributeType);
……
}
}
[Serializable, Flags]
public enum DegenerateTargets
{
Method = 0x01,
Getter = 0x02,
Setter = 0x04
Adder = 0x08,
Remover = 0x10,
Event = Adder | Remover ,
Property = Getter | Setter,
All = Method | Event | Property,
None = 0,
}
DegenerateAttribute为所有退化自定义属性提供抽象基类,其派生类用于指定退化的方法(Method)或属性(Property)的具体读写器或事件(Event)的具体Adder或Remover。给出他的类信息可由其静态函数和嵌套类可以得到相应的IDegenerateProvider的实例。
l 理想的适应ReadOnly退化包装的Sysetm.Collections.IList的C#语言完整声明,ReadOnly退化属性类:ReadOnlyDegenerateAttribute的C#语言完整声明:
public interface IList : ICollection, IEnumerable
{
[ReadOnlyDegenerate]
int Add(object value);
[ReadOnlyDegenerate]
void Clear();
bool Contains(object value);
int IndexOf(object value);
[ReadOnlyDegenerate]
void Insert(int index, object value);
[ReadOnlyDegenerate]
void Remove(object value);
[ReadOnlyDegenerate]
void RemoveAt(int index);
[ReadOnlyDegenerate (DegenerateTagets.Setter)]
object this[int index] { get; set; }
}
[Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)]
public sealed class ReadOnlyDegenerateAttribute : DegenerateAttribute
{
public ReadOnlyAttribute();
public ReadOnlyAttribute(DegenerateTargets targets);
}
4.3 模型的优势
如果仅仅对某个接口人工代码实现指定退化的类。那么这个接口的继承接口的退化工作将会是由许多重复的,这样的人工代码实现将是无效率的。那么这个退化的信息应该标识到接口声明里,那么这样的信息不仅是给这个接口与这个退化的,还将提供给继承接口去完成这样的退化。
所有的接口都客观存在其退化和同步化接口封装,那么这样的封装类不应该由程序员来实现,而应该有程序动态生成。
5 如何发送代码实现动态封装类
在退化供应器的指导下我们退化的工作知道那些功能因该退化那些应该调用,而同步化的封装是出人意料的简单,每个方法的实现都有同种模式来实现。因为本文重在提供动态封装的模式。而发送代码的工作牵扯到微软中间语言(MSIL),而这只是技术实现,当然我们在其它支持反射及代码发送的平台下一样可以实现它。而且应该的是标准库中所应该提供的部分。
下面是同步化接口封装的C#语言实现的关键部分:
private static void ImplementMethodSyncInvoke(TypeBuilder tb, MethodInfo mi, FieldBuilder fb, FieldBuilder rfb)
{
Type[] typeArray1 = Boxer.ParamsTypes(mi.GetParameters());
MethodBuilder builder1 = tb.DefineMethod(mi.Name, Boxer. InterfaceMethodAttributes, mi.ReturnType, typeArray1);
ILGenerator generator1 = builder1.GetILGenerator();
generator1.DeclareLocal(typeof(object));
//为返回值申请本地内存空间
if (mi.ReturnType != typeof(void))
generator1.DeclareLocal(mi.ReturnType);
//载入同步根实例
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldfld, rfb);
generator1.Emit(OpCodes.Dup);
generator1.Emit(OpCodes.Stloc_0);
//进入同步化区
generator1.Emit(OpCodes.Call, Boxer.ThreadEnterMethod);
//为保证不会因为调用过程的异常造成程序跳出,而形成死锁,需要try{}finally{}处理退出同步化区
//try{
generator1.BeginExceptionBlock();
generator1.Emit(OpCodes.Ldarg_0);
//为调用载入对象
generator1.Emit(OpCodes.Ldfld, fb);
//载入所有参数
int num1 = typeArray1.Length;
if (num1 > 0)
{
generator1.Emit(OpCodes.Ldarg_1);
if (num1 > 1)
{
generator1.Emit(OpCodes.Ldarg_2);
if (num1 > 2)
{
generator1.Emit(OpCodes.Ldarg_3);
for (int num2 = 4; num2 <= num1; num2++)
generator1.Emit(OpCodes.Ldarg_S, (byte) num2);
}
}
}
//调用
generator1.Emit(OpCodes.Callvirt, mi);
//存储返回值
if (mi.ReturnType != typeof(void))
generator1.Emit(OpCodes.Stloc_1);
//}
//finally{
generator1.BeginFinallyBlock();
generator1.Emit(OpCodes.Ldloc_0);
generator1.Emit(OpCodes.Call, Boxer.ThreadExitMethod);
//}
generator1.EndExceptionBlock();
//载入返回值
if (mi.ReturnType != typeof(void))
generator1.Emit(OpCodes.Ldloc_1);
generator1.Emit(OpCodes.Ret);
tb.DefineMethodOverride(builder1, mi);
}
private static void ImplementInterface(TypeBuilder tb, Type interfaceType, FieldBuilder fb, FieldBuilder rfb)
{
//实现Methods
MethodInfo[] infoArray1 = interfaceType.GetMethods();
for (int num1 = 0; num1 < infoArray1.Length; num1++)
{
MethodInfo info1 = infoArray1[num1];
Boxer.ImplementMethodSyncInvoke(tb, info1, fb, rfb);
}
//实现Properties
PropertyInfo[] infoArray2 = interfaceType.GetProperties();
for (int num2 = 0; num2 < infoArray2.Length; num2++)
{
PropertyInfo info2 = infoArray2[num2];
MethodInfo info3 = info2.GetGetMethod(true);
if (info3 != null)
Boxer.ImplementMethodSyncInvoke(tb, info3, fb, rfb);
info3 = info2.GetSetMethod(true);
if (info3 != null)
Boxer.ImplementMethodSyncInvoke(tb, info3, fb, rfb);
}
//实现Events
EventInfo[] infoArray3 = interfaceType.GetEvents();
for (int num3 = 0; num3 < infoArray3.Length; num3++)
{
EventInfo info4 = infoArray3[num3];
MethodInfo info5 = info4.GetAddMethod(true);
if (info5 != null)
Boxer.ImplementMethodSyncInvoke(tb, info5, fb, rfb);
info5 = info4.GetRemoveMethod(true);
if (info5 != null)
Boxer.ImplementMethodSyncInvoke(tb, info5, fb, rfb);
}
}
internal static object InternalSynchronize(object target, Type interfaceType, object syncRoot)
{
object obj1;
lock (Boxer.SynchronizedTable)
{
//找出已经生成的对于动态类的构造函数
ConstructorInfo info1 = (ConstructorInfo) Boxer.SynchronizedTable[interfaceType];
if (info1 == null)
{
Type[] typeArray1 = new Type[2] { interfaceType, typeof(object) } ;
TypeBuilder builder1 = Boxer.BoxerModuleBuilder.DefineType("BoxedClasses.Synchronized" + (++Boxer.SynchronizedCount), TypeAttributes.Public);
builder1.SetCustomAttribute(new CustomAttributeBuilder(Boxer.SynchronizedAttribute.Constructor, new object[0]));
builder1.AddInterfaceImplementation(interfaceType);
//构造字段target
FieldBuilder builder2 = builder1.DefineField(Boxer.FindName(interfaceType, "_target"), interfaceType, Boxer.FieldAttribute);
//构造字段syncroot
FieldBuilder builder3 = builder1.DefineField(Boxer.FindName(interfaceType, "_syncroot"), typeof(object), Boxer.FieldAttribute);
//构造唯一的构造方法
ConstructorBuilder builder4 = builder1.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, typeArray1);
ILGenerator generator1 = builder4.GetILGenerator();
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Call, Boxer.ObjectConstructor);
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldarg_1);
generator1.Emit(OpCodes.Stfld, builder2);
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldarg_2);
generator1.Emit(OpCodes.Stfld, builder3);
generator1.Emit(OpCodes.Ret);
Boxer.ImplementInterface(builder1, interfaceType, builder2, builder3);
Type[] typeArray3 = interfaceType.GetInterfaces();
for (int num1 = 0; num1 < typeArray3.Length; num1++)
{
Type type1 = typeArray3[num1];
Boxer.ImplementInterface(builder1, type1, builder2, builder3);
}
//将此实例加入全局表,以便后用
Boxer.SynchronizedTable.Add(interfaceType, (info1 = builder1.CreateType().GetConstructor(typeArray1)));
}
object[] objArray1 = new object[2] { target, syncRoot } ;
obj1 = info1.Invoke(objArray1);
}
return obj1;
}
6 新的语法规范
由.NET 2.0 基础类库对范型的应用来看,这里的退化和同步化当然也可以作出新的语法规范方便程序员调用。下面以C#语言为例介绍新的语法规范。
6.1 同步化
我们可以通过关键字synchronize和on来得到对应的同步化的类实例,通过issynchronized得到同步化检查,例如:
IList list;
object syncRoot;
……
//[] 为可选部分
IList slist = list synchronize IList [on syncRoot ];
//内部实现=(IList)Boxer.Synchronize(list[, syncRoot]);
bool issync = slist issynchronized IList [on syncRoot];
//内部实现=Boxer.IsSynchronized(slist [, syncRoot]);
6.2 退化
我们可以通过关键字degenerate 和on可获得退化类实例,通过isdegenerated得到同步化检查,例如:
IList list;
IDegenerateProvider degenerateProvider;
……
IList dlist = list degenerate IList on typeof(ReadOnlyDegenerateAttribute);
//内部实现= (IList)Boxer.Degenerate(list, typeof(ReadOnlyDegenerateAttribute));
IList dlist1 = list degenerate IList on degenerateProvider;
///内部实现= (IList)Boxer.Degenerate(list, degenerateProvider);
Bool isdeg = dlist isdegenerated IList on typeof(ReadOnlyDegenerateAttribute);
//内部实现=(IList)Boxer.IsDegenerated(list, typeof(ReadOnlyDegenerateAttribute));
6.3 无退化接口封装
我们可以通过关键字box可获得接口封装实例,通过isboxed得到同步化检查,例如:
IList list = new ArrayList();
……
IList blist = list box IList;
//内部实现= (IList)Boxer.Degenerate(list, typeof(NonDegenerateAttribute));
Bool isb = blist isboxed IList;
//内部实现=(IList)Boxer.IsDegenerated(list, typeof(NonDegenerateAttribute));
本文地址:http://com.8s8s.com/it/it44174.htm