internal NestedTypeGetter(CLRClass klass) { this.klass = klass; }
internal static CLRClass Define(System.Type type, CLRClass klass) { // TODO: (writer) lock ? CLRClass existing; if (cache.TryGetValue(type, out existing)) return existing; cache[type] = klass; return klass; }
internal static CLRClass Load(System.Type type, Frame caller, bool makeConstant) { if (type == null) return null; CLRClass klass; if (!TryLoad(type, out klass)) { System.Type baseType = type.BaseType; CLRClass baseClass = baseType == null ? null : Load(baseType, caller, makeConstant && baseType.Assembly == type.Assembly); if (baseClass != null) { klass = new CLRClass(type, baseClass, Type.Class); klass.my_class = new CLRClass(type, baseClass.my_class, Type.IClass); System.Type[] inherited = baseType.GetInterfaces(); foreach (System.Type iface in type.GetInterfaces()) { if (0 > System.Array.IndexOf(inherited, iface)) Class.rb_include_module(caller, klass, Load(iface, caller, false)); } } else { if (type.IsInterface) { klass = new CLRClass(type, null, Type.Module); klass.my_class = new CLRClass(type, Init.rb_cModule, Type.IClass); } else { klass = new CLRClass(type, Init.rb_cObject, Type.Class); klass.my_class = new CLRClass(type, Init.rb_cClass, Type.IClass); } foreach (System.Type iface in type.GetInterfaces()) Class.rb_include_module(caller, klass, Load(iface, caller, false)); } Augmentations.Augment(type, klass, caller); klass = Define(type, klass); } if (makeConstant) { Class context = context = Ruby.Runtime.Init.rb_cObject; if (type.Namespace != null) { foreach (string Namespace in type.Namespace.Split('.')) { Class innerContext; string constant = FormatConstant(Namespace); if (context.const_defined(constant, false) && (innerContext = context.const_get(constant, caller) as Class) != null) context = innerContext; else context.define_const(constant, context = new CLRNamespace(Namespace)); } } if (type.IsNested) { // nested types can be loaded by a getter in their owner // ruby: Namespace::Type.InnerType } else if (type.IsGenericTypeDefinition) { string name = type.Name.Substring(0, type.Name.LastIndexOf('`')); string containerName = type.Namespace == null ? name : type.Namespace + "." + name; // if a non-generic type exists with the same name // we can use that in the construction of a generic type System.Type container = type.Assembly.GetType(containerName); // otherwise we much build a GenericContainer if (container == null) { string constant = FormatConstant(name); if (!context.const_defined(constant)) context.define_const(constant, new GenericContainer(type.Assembly, containerName, null)); } } else { context.define_const(FormatConstant(type.Name), klass); } } return klass; }
internal static bool TryLoad(System.Type type, out CLRClass klass) { // TODO: (reader) lock ? return cache.TryGetValue(type, out klass); }