lib/caricature/clr/descriptor.rb in caricature-0.7.2 vs lib/caricature/clr/descriptor.rb in caricature-0.7.5

- old
+ new

@@ -1,47 +1,108 @@ module Caricature # Contains the logic to collect members from a CLR type module ClrMemberCollector + attr_reader :class_events, :events + private - # collects the instance members for a CLR type. - # makes sure it can handle indexers for properties etc. - def collect_members_from(meths, properties, instance_member=true) + # collects the instance members for a CLR type. + # makes sure it can handle indexers for properties etc. + def build_member_collections(context={}, instance_member=true) - mem = [] - mem += meths.collect do |mi| - MemberDescriptor.new(mi.name.underscore, mi.return_type, instance_member) - end - properties.each do |pi| - prop_name = property_name_from(pi) - mem << MemberDescriptor.new(prop_name, pi.property_type, instance_member) - mem << MemberDescriptor.new("__setitem__", nil, instance_member) if prop_name == "__getitem__" - mem << MemberDescriptor.new("#{prop_name}=", nil, instance_member) if pi.can_write and prop_name != "__getitem__" - end - mem + build_event_collection(context, instance_member) + + mem = [] + mem += build_method_collection(context, instance_member) + mem += build_property_collection(context, instance_member) + mem + end + + def build_property_collection(context, instance_member) + context[:properties].inject([]) do |res, pi| + prop_name = property_name_from(pi) + res << MemberDescriptor.new(prop_name, pi.property_type, instance_member) + res << MemberDescriptor.new("set_Item", nil, instance_member) if prop_name == "get_Item" + res << MemberDescriptor.new("#{prop_name}=", nil, instance_member) if pi.can_write and prop_name != "get_Item" + res end + end - # gets the property name from the +PropertyInfo+ - # when the property is an indexer it will return +[]+ - def property_name_from(property_info) - return property_info.name.underscore if property_info.get_index_parameters.empty? - "__getitem__" - end - - # the binding flags for instance members of a CLR type - def instance_flags - System::Reflection::BindingFlags.public | System::Reflection::BindingFlags.instance - end - - # the binding flags for class members of a CLR type - def class_flags - System::Reflection::BindingFlags.public | System::Reflection::BindingFlags.static + def build_method_collection(context, instance_member) + context[:methods].inject([]) do |meths, mi| + meths << MemberDescriptor.new(mi.name.underscore, mi.return_type, instance_member) unless event?(mi.name, instance_member) + meths end + end + def build_event_collection(context, instance_member) + context[:events].inject(evts=[]) { |evc, ei| evc << ClrEventDescriptor.new(ei.name, instance_member) } + (instance_member ? @events = evts : @class_events = evts) + end + + # indicates if this member is an event + def event?(name, instance_member) + ((instance_member ? @events : @class_events)||[]).any? { |en| /^(add|remove)_#{en.event_name}/i =~ name } + end + + # gets the property name from the +PropertyInfo+ + # when the property is an indexer it will return +[]+ + def property_name_from(property_info) + return property_info.name.underscore if property_info.get_index_parameters.empty? + "get_Item" + end + + # the binding flags for instance members of a CLR type + def instance_flags + System::Reflection::BindingFlags.public | System::Reflection::BindingFlags.instance + end + + # the binding flags for class members of a CLR type + def class_flags + System::Reflection::BindingFlags.public | System::Reflection::BindingFlags.static + end + + def event_flags + non_public_flag | instance_flags + end + + def class_event_flags + non_public_flag | class_flags + end + + def non_public_flag + System::Reflection::BindingFlags.non_public + end + end + class ClrEventDescriptor + + attr_reader :event_name + + def initialize(event_name, instance_member=true) + @event_name, @instance_member = event_name, instance_member + end + + def instance_member? + @instance_member + end + + def add_method_name + "add_#{event_name}" + end + + def remove_method_name + "remove_#{event_name}" + end + + def to_s + "<#{self.class}:#{object_id} @event_name=\"#{event_name}\">" + end + end + # describes clr interfaces. # Because CLR interfaces can't have static members this descriptor does not collect any class members class ClrInterfaceDescriptor < TypeDescriptor include ClrMemberCollector @@ -49,14 +110,16 @@ # collects instance members on this interface # it will collect properties, methods and property setters def initialize_instance_members_for(klass) clr_type = klass.to_clr_type - properties = clr_type.collect_interface_properties - methods = clr_type.collect_interface_methods + context = {} + context[:properties] = clr_type.collect_interface_properties + context[:methods] = clr_type.collect_interface_methods + context[:events] = clr_type.collect_interface_events - @instance_members = collect_members_from methods, properties + @instance_members = build_member_collections context end # this method is empty because an interface can't have static members def initialize_class_members_for(klass); end @@ -70,23 +133,27 @@ # collects all the instance members of the provided CLR class type def initialize_instance_members_for(klass) clr_type = klass.to_clr_type - methods = clr_type.get_methods(instance_flags) - properties = clr_type.get_properties(instance_flags) + context = {} + context[:methods] = clr_type.get_methods(instance_flags) + context[:properties] = clr_type.get_properties(instance_flags) + context[:events] = clr_type.get_events(event_flags) - @instance_members = collect_members_from methods, properties + @instance_members = build_member_collections context end # collects all the static members of the provided CLR class type def initialize_class_members_for(klass) clr_type = klass.to_clr_type - methods = clr_type.get_methods(class_flags) - properties = clr_type.get_properties(class_flags) + context = {} + context[:methods] = clr_type.get_methods(class_flags) + context[:properties] = clr_type.get_properties(class_flags) + context[:events] = clr_type.get_events(class_event_flags) - @class_members = collect_members_from methods, properties, false + @class_members = build_member_collections context, false end end end \ No newline at end of file