caricature 0.7.5 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/README.rdoc +97 -97
  2. data/Rakefile +309 -310
  3. data/caricature.gemspec +123 -110
  4. data/lib/caricature/bacon/integration.rb +75 -75
  5. data/lib/caricature/bacon.rb +2 -2
  6. data/lib/caricature/clr/descriptor.rb +159 -159
  7. data/lib/caricature/clr/event_verification.rb +56 -56
  8. data/lib/caricature/clr/expectation.rb +100 -100
  9. data/lib/caricature/clr/isolation.rb +78 -78
  10. data/lib/caricature/clr/isolator.rb +252 -252
  11. data/lib/caricature/clr/messenger.rb +51 -49
  12. data/lib/caricature/clr/method_call_recorder.rb +96 -96
  13. data/lib/caricature/expectation.rb +1 -1
  14. data/lib/caricature/method_call_recorder.rb +3 -3
  15. data/lib/caricature/rspec/integration.rb +118 -118
  16. data/lib/caricature/version.rb +5 -5
  17. data/lib/caricature.rb +25 -25
  18. data/spec/bacon/integration/callback_spec.rb +156 -156
  19. data/spec/bacon/integration/clr_to_clr_spec.rb +325 -253
  20. data/spec/bacon/integration/event_spec.rb +97 -97
  21. data/spec/bacon/integration/indexer_spec.rb +27 -27
  22. data/spec/bacon/spec_helper.rb +4 -4
  23. data/spec/bacon/unit/descriptor_spec.rb +212 -212
  24. data/spec/bacon/unit/sword_spec.rb +39 -39
  25. data/spec/bacon/unit/verification_spec.rb +103 -103
  26. data/spec/bin/ClrModels.dll +0 -0
  27. data/spec/bin/ClrModels.dll.mdb +0 -0
  28. data/spec/fixtures/ExplodingCar.cs +56 -0
  29. data/spec/fixtures/ExposedChangedSubscriber.cs +26 -0
  30. data/spec/fixtures/ExposingWarrior.cs +58 -0
  31. data/spec/fixtures/IExplodingWarrior.cs +10 -0
  32. data/spec/fixtures/IExposing.cs +9 -0
  33. data/spec/fixtures/IExposingBridge.cs +9 -0
  34. data/spec/fixtures/IExposingWarrior.cs +8 -0
  35. data/spec/fixtures/IHaveAnIndexer.cs +8 -0
  36. data/spec/fixtures/IWarrior.cs +13 -0
  37. data/spec/fixtures/IWeapon.cs +9 -0
  38. data/spec/fixtures/IndexerCaller.cs +17 -0
  39. data/spec/fixtures/IndexerContained.cs +20 -0
  40. data/spec/fixtures/MyClassWithAStatic.cs +16 -0
  41. data/spec/fixtures/Ninja.cs +34 -0
  42. data/spec/fixtures/Samurai.cs +29 -0
  43. data/spec/fixtures/StaticCaller.cs +12 -0
  44. data/spec/fixtures/Sword.cs +16 -0
  45. data/spec/fixtures/SwordWithStatics.cs +19 -0
  46. data/spec/fixtures/clr_interaction.rb +61 -0
  47. data/spec/fixtures/dagger.rb +11 -0
  48. data/spec/fixtures/dagger_with_class_members.rb +11 -0
  49. data/spec/fixtures/sheath.rb +19 -0
  50. data/spec/fixtures/soldier.rb +29 -0
  51. data/spec/fixtures/soldier_with_class_members.rb +7 -0
  52. data/spec/fixtures/swift_cleanup_crew.rb +21 -0
  53. data/spec/fixtures/with_class_methods.rb +11 -0
  54. data/spec/{models → models.notused}/ClrModels.cs +241 -241
  55. data/spec/{models → models.notused}/ruby_models.rb +150 -150
  56. data/spec/rspec/integration/callback_spec.rb +156 -156
  57. data/spec/rspec/integration/clr_to_clr_spec.rb +254 -254
  58. data/spec/rspec/integration/clr_to_ruby_spec.rb +227 -227
  59. data/spec/rspec/integration/indexer_spec.rb +27 -27
  60. data/spec/rspec/integration/ruby_to_ruby_spec.rb +271 -271
  61. data/spec/rspec/spec_helper.rb +12 -12
  62. data/spec/rspec/unit/core_ext_spec.rb +87 -87
  63. data/spec/rspec/unit/descriptor_spec.rb +210 -210
  64. data/spec/rspec/unit/event_spec.rb +16 -16
  65. data/spec/rspec/unit/expectation_spec.rb +300 -300
  66. data/spec/rspec/unit/interop_spec.rb +29 -29
  67. data/spec/rspec/unit/isolation_spec.rb +86 -86
  68. data/spec/rspec/unit/isolator_spec.rb +219 -219
  69. data/spec/rspec/unit/messaging_spec.rb +310 -310
  70. data/spec/rspec/unit/method_call_spec.rb +342 -342
  71. data/spec/rspec/unit/sword_spec.rb +39 -39
  72. data/spec/rspec/unit/verification_spec.rb +103 -103
  73. data/spec/spec_helper.rb +16 -15
  74. metadata +42 -11
@@ -1,79 +1,79 @@
1
- module Caricature
2
-
3
-
4
-
5
- class Isolation # :nodoc:
6
-
7
- # the event subscriptions collected at runtime
8
- attr_reader :events
9
-
10
- # the event subscriptions collected at runtime
11
- def events
12
- @events ||= {}
13
- end
14
-
15
- # adds an event subscription
16
- def add_event_subscription(event_name, mode, handler)
17
- events[mode] ||= {}
18
- nm = event_name_for(event_name)
19
- events[mode][nm] ||= []
20
- events[mode][nm] << handler
21
- end
22
-
23
- # removes an event subscription
24
- def remove_event_subscription(event_name, mode, handler)
25
- ((events[mode] ||= {})[event_name_for(event_name)] ||=[]).delete(handler)
26
- end
27
-
28
- # def add_event_expectation(name, mode, *args, &handler)
29
- # end
30
-
31
- def internal_create_override(method_name, mode=:instance, &block)
32
- builder = ExpectationBuilder.new method_name
33
- block.call builder unless block.nil?
34
- exp = builder.build
35
- exp.events = events[mode]
36
- expectations.add_expectation exp, mode
37
- exp
38
- end
39
-
40
- def verify_event_raise(event_name, mode= :instance, &block)
41
- verification = EventVerification.new(event_name, recorder, mode)
42
- block.call verification unless block.nil?
43
- verification
44
- end
45
-
46
- class << self
47
-
48
- # Creates an isolation object complete with proxy and method call recorder
49
- # It works out which isolation it needs to create and provide and initializes the
50
- # method call recorder
51
- def for(subject, recorder = MethodCallRecorder.new, expectations = Expectations.new)
52
- context = IsolatorContext.new subject, recorder, expectations
53
- isolation_strategy = subject.clr_type? ? get_clr_isolation_strategy(subject) : RubyIsolator
54
-
55
- isolator = isolation_strategy.for context
56
- new(isolator, context)
57
- isolator.isolation
58
- end
59
-
60
- private
61
-
62
- # decides which startegy to use for mocking a CLR object.
63
- # When the provided subject is an interface it will return a +ClrInterfaceIsolator+
64
- # otherwise it will return a +ClrIsolator+
65
- def get_clr_isolation_strategy(subject)
66
- return ClrInterfaceIsolator if subject.respond_to? :class_eval and !subject.respond_to? :new
67
- ClrIsolator
68
- end
69
- end
70
-
71
- private
72
-
73
- def event_name_for(method_name) #:nodoc:
74
- method_name.gsub(/^(add|remove)_/, '').underscore.to_sym
75
- end
76
-
77
- end
78
-
1
+ module Caricature
2
+
3
+
4
+
5
+ class Isolation # :nodoc:
6
+
7
+ # the event subscriptions collected at runtime
8
+ attr_reader :events
9
+
10
+ # the event subscriptions collected at runtime
11
+ def events
12
+ @events ||= {}
13
+ end
14
+
15
+ # adds an event subscription
16
+ def add_event_subscription(event_name, mode, handler)
17
+ events[mode] ||= {}
18
+ nm = event_name_for(event_name)
19
+ events[mode][nm] ||= []
20
+ events[mode][nm] << handler
21
+ end
22
+
23
+ # removes an event subscription
24
+ def remove_event_subscription(event_name, mode, handler)
25
+ ((events[mode] ||= {})[event_name_for(event_name)] ||=[]).delete(handler)
26
+ end
27
+
28
+ # def add_event_expectation(name, mode, *args, &handler)
29
+ # end
30
+
31
+ def internal_create_override(method_name, mode=:instance, &block)
32
+ builder = ExpectationBuilder.new method_name
33
+ block.call builder unless block.nil?
34
+ exp = builder.build
35
+ exp.events = events[mode]
36
+ expectations.add_expectation exp, mode
37
+ exp
38
+ end
39
+
40
+ def verify_event_raise(event_name, mode= :instance, &block)
41
+ verification = EventVerification.new(event_name, recorder, mode)
42
+ block.call verification unless block.nil?
43
+ verification
44
+ end
45
+
46
+ class << self
47
+
48
+ # Creates an isolation object complete with proxy and method call recorder
49
+ # It works out which isolation it needs to create and provide and initializes the
50
+ # method call recorder
51
+ def for(subject, recorder = MethodCallRecorder.new, expectations = Expectations.new)
52
+ context = IsolatorContext.new subject, recorder, expectations
53
+ isolation_strategy = subject.clr_type? ? get_clr_isolation_strategy(subject) : RubyIsolator
54
+
55
+ isolator = isolation_strategy.for context
56
+ new(isolator, context)
57
+ isolator.isolation
58
+ end
59
+
60
+ private
61
+
62
+ # decides which startegy to use for mocking a CLR object.
63
+ # When the provided subject is an interface it will return a +ClrInterfaceIsolator+
64
+ # otherwise it will return a +ClrIsolator+
65
+ def get_clr_isolation_strategy(subject)
66
+ return ClrInterfaceIsolator if subject.respond_to? :class_eval and !subject.respond_to? :new
67
+ ClrIsolator
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def event_name_for(method_name) #:nodoc:
74
+ method_name.gsub(/^(add|remove)_/, '').underscore.to_sym
75
+ end
76
+
77
+ end
78
+
79
79
  end
@@ -1,253 +1,253 @@
1
- module Caricature
2
-
3
- # Groups the methods for interception together
4
- # this is a mix-in for the created isolations for classes
5
- module Interception
6
-
7
- # the class methods of this intercepting object
8
- module ClassMethods
9
-
10
- # Raises an event on the isolation
11
- # You can specify the arguments in the block or as parameters
12
- #
13
- # Example
14
- #
15
- # an_isolation.class.raise_event :on_property_changed do |raiser|
16
- # raiser.with an_isolation, System::EventArgs.empty
17
- # end
18
- #
19
- # is equivalent to:
20
- #
21
- # an_isolation.class.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
22
- #
23
- # or
24
- #
25
- # an_isolation.class.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
26
- #
27
- # You will most likely use this method when you want to verify logic in an event handler
28
- # You will most likely use this method when you want to verify logic in an event handler
29
- def raise_event(event_name, *args, &block)
30
- isolation_context.add_event_expectation event_name, :class, *args, &block
31
- end
32
-
33
- # Verifies whether the specified event was raised
34
- #
35
- # You will probably be using this method only when you're interested in whether an event has been raised
36
- # during the course of the test you're running.
37
- def did_raise_event?(event_name, &b)
38
- isolation_context.verify_event_raise event_name, :class, &b
39
- end
40
-
41
- end
42
-
43
- # Raises an event on the isolation
44
- # You can specify the arguments in the block or as parameters
45
- #
46
- # Example
47
- #
48
- # an_isolation.raise_event :on_property_changed do |raiser|
49
- # raiser.with an_isolation, System::EventArgs.empty
50
- # end
51
- #
52
- # is equivalent to:
53
- #
54
- # an_isolation.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
55
- #
56
- # or
57
- #
58
- # an_isolation.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
59
- #
60
- # You will most likely use this method when you want to verify logic in an event handler
61
- def raise_event(event_name, *args, &block)
62
- isolation_context.add_event_expectation event_name, :instance, *args, &block
63
- end
64
-
65
- # Raises an event on the isolation
66
- # You can specify the arguments in the block or as parameters
67
- #
68
- # Example
69
- #
70
- # an_isolation.raise_class_event :on_property_changed do |raiser|
71
- # raiser.with an_isolation, System::EventArgs.empty
72
- # end
73
- #
74
- # is equivalent to:
75
- #
76
- # an_isolation.raise_class_event :on_property_changed, an_isolation, System::EventArgs.empty
77
- #
78
- # or
79
- #
80
- # an_isolation.raise_class_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
81
- #
82
- # You will most likely use this method when you want to verify logic in an event handler
83
- def raise_class_event(event_name, *args, &block)
84
- self.class.raise_event event_name, *args, &block
85
- end
86
-
87
- # Verifies whether the specified event was raised
88
- #
89
- # You will probably be using this method only when you're interested in whether an event has been raised
90
- # during the course of the test you're running.
91
- def did_raise_event?(event_name, &b)
92
- isolation_context.verify_event_raise event_name, :instance, &b
93
- end
94
-
95
- # Verifies whether the specified event was raised
96
- #
97
- # You will probably be using this method only when you're interested in whether an event has been raised
98
- # during the course of the test you're running.
99
- def did_raise_class_event?(event_name, &b)
100
- self.class.did_raise_event? event_name, &b
101
- end
102
-
103
- end
104
-
105
- # A proxy to CLR objects that records method calls.
106
- # this implements all the public instance methods of the class when you use it in ruby code
107
- # When you use it in a CLR class you're bound to CLR rules and it only overrides the methods
108
- # that are marked as virtual. We also can't isolate static or sealed types at the moment.
109
- class ClrIsolator < Isolator
110
-
111
-
112
- # Implementation of the template method that creates
113
- # an isolator for a class defined in a CLR language.
114
- def initialize(context)
115
- super
116
- instance = nil
117
- sklass = context.subject
118
- unless context.subject.respond_to?(:class_eval)
119
- sklass = context.subject.class
120
- instance = context.subject
121
- end
122
- @descriptor = ClrClassDescriptor.new sklass
123
- instance ||= sklass.new unless sklass.to_clr_type.is_abstract
124
- build_isolation sklass, instance
125
- end
126
-
127
- # initializes the messaging strategy for the isolator
128
- def initialize_messenger
129
- @context.messenger = ClrClassMessenger.new @context.expectations, @subject
130
- end
131
-
132
- # builds the Isolator class for the specified subject
133
- def create_isolation_for(subj)
134
- members = @descriptor.instance_members
135
- class_members = @descriptor.class_members
136
- events = @descriptor.events
137
- class_events = @descriptor.class_events
138
-
139
- klass = Object.const_set(class_name(subj), Class.new(subj))
140
- klass.class_eval do
141
-
142
- include Interception
143
-
144
- # access to the proxied subject
145
- def ___super___
146
- isolation_context.instance
147
- end
148
-
149
- def initialize(*args)
150
- self
151
- end
152
-
153
- members.each do |mem|
154
- nm = mem.name.to_s.to_sym
155
- define_method nm do |*args|
156
- b = nil
157
- b = Proc.new { yield } if block_given?
158
- isolation_context.send_message(nm, mem.return_type, *args, &b)
159
- end unless nm == :to_string
160
- end
161
-
162
- class_members.each do |mn|
163
- mn = mn.name.to_s.to_sym
164
- define_cmethod mn do |*args|
165
- b = nil
166
- b = Proc.new { yield } if block_given?
167
- isolation_context.send_class_message(mn, nil, *args, &b)
168
- end
169
- end
170
-
171
- evts = (events + class_events).collect do |evt|
172
- %w(add remove).inject("") do |res, nm|
173
- res << <<-end_event_definition
174
-
175
- def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
176
- self.isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
177
- end
178
-
179
- end_event_definition
180
- end
181
-
182
- end.join("\n")
183
-
184
- klass.class_eval evts
185
-
186
- #puts evts
187
-
188
- end
189
-
190
- klass
191
- end
192
-
193
- end
194
-
195
- # An +Isolator+ for CLR interfaces.
196
- # this implements all the methods that are defined on the interface.
197
- class ClrInterfaceIsolator < Isolator
198
-
199
- # Implementation of the template method that creates
200
- # an isolator for an interface defined in a CLR language.
201
- def initialize(context)
202
- super
203
- sklass = context.subject
204
- @descriptor = ClrInterfaceDescriptor.new sklass
205
- build_isolation sklass
206
- end
207
-
208
- # initializes the messaging strategy for the isolator
209
- def initialize_messenger
210
- @context.messenger = ClrInterfaceMessenger.new @context.expectations
211
- end
212
-
213
- # builds the actual +isolator+ for the CLR interface
214
- def create_isolation_for(subj)
215
- proxy_members = @descriptor.instance_members
216
- events = @descriptor.events
217
-
218
- klass = Object.const_set(class_name(subj), Class.new)
219
- klass.class_eval do
220
-
221
- include subj
222
- include Interception
223
-
224
- proxy_members.each do |mem|
225
- nm = mem.name.to_s.to_sym
226
- define_method nm do |*args|
227
- b = nil
228
- b = Proc.new { yield } if block_given?
229
- isolation_context.send_message(nm, mem.return_type, *args, &b)
230
- end
231
- end
232
-
233
-
234
- end
235
-
236
- evts = events.collect do |evt|
237
- %w(add remove).inject("") do |res, nm|
238
- res << <<-end_event_definition
239
-
240
- def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
241
- isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
242
- end
243
-
244
- end_event_definition
245
- end
246
- end.join("\n")
247
- klass.class_eval evts
248
-
249
- klass
250
- end
251
- end
252
-
1
+ module Caricature
2
+
3
+ # Groups the methods for interception together
4
+ # this is a mix-in for the created isolations for classes
5
+ module Interception
6
+
7
+ # the class methods of this intercepting object
8
+ module ClassMethods
9
+
10
+ # Raises an event on the isolation
11
+ # You can specify the arguments in the block or as parameters
12
+ #
13
+ # Example
14
+ #
15
+ # an_isolation.class.raise_event :on_property_changed do |raiser|
16
+ # raiser.with an_isolation, System::EventArgs.empty
17
+ # end
18
+ #
19
+ # is equivalent to:
20
+ #
21
+ # an_isolation.class.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
22
+ #
23
+ # or
24
+ #
25
+ # an_isolation.class.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
26
+ #
27
+ # You will most likely use this method when you want to verify logic in an event handler
28
+ # You will most likely use this method when you want to verify logic in an event handler
29
+ def raise_event(event_name, *args, &block)
30
+ isolation_context.add_event_expectation event_name, :class, *args, &block
31
+ end
32
+
33
+ # Verifies whether the specified event was raised
34
+ #
35
+ # You will probably be using this method only when you're interested in whether an event has been raised
36
+ # during the course of the test you're running.
37
+ def did_raise_event?(event_name, &b)
38
+ isolation_context.verify_event_raise event_name, :class, &b
39
+ end
40
+
41
+ end
42
+
43
+ # Raises an event on the isolation
44
+ # You can specify the arguments in the block or as parameters
45
+ #
46
+ # Example
47
+ #
48
+ # an_isolation.raise_event :on_property_changed do |raiser|
49
+ # raiser.with an_isolation, System::EventArgs.empty
50
+ # end
51
+ #
52
+ # is equivalent to:
53
+ #
54
+ # an_isolation.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
55
+ #
56
+ # or
57
+ #
58
+ # an_isolation.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
59
+ #
60
+ # You will most likely use this method when you want to verify logic in an event handler
61
+ def raise_event(event_name, *args, &block)
62
+ isolation_context.add_event_expectation event_name, :instance, *args, &block
63
+ end
64
+
65
+ # Raises an event on the isolation
66
+ # You can specify the arguments in the block or as parameters
67
+ #
68
+ # Example
69
+ #
70
+ # an_isolation.raise_class_event :on_property_changed do |raiser|
71
+ # raiser.with an_isolation, System::EventArgs.empty
72
+ # end
73
+ #
74
+ # is equivalent to:
75
+ #
76
+ # an_isolation.raise_class_event :on_property_changed, an_isolation, System::EventArgs.empty
77
+ #
78
+ # or
79
+ #
80
+ # an_isolation.raise_class_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
81
+ #
82
+ # You will most likely use this method when you want to verify logic in an event handler
83
+ def raise_class_event(event_name, *args, &block)
84
+ self.class.raise_event event_name, *args, &block
85
+ end
86
+
87
+ # Verifies whether the specified event was raised
88
+ #
89
+ # You will probably be using this method only when you're interested in whether an event has been raised
90
+ # during the course of the test you're running.
91
+ def did_raise_event?(event_name, &b)
92
+ isolation_context.verify_event_raise event_name, :instance, &b
93
+ end
94
+
95
+ # Verifies whether the specified event was raised
96
+ #
97
+ # You will probably be using this method only when you're interested in whether an event has been raised
98
+ # during the course of the test you're running.
99
+ def did_raise_class_event?(event_name, &b)
100
+ self.class.did_raise_event? event_name, &b
101
+ end
102
+
103
+ end
104
+
105
+ # A proxy to CLR objects that records method calls.
106
+ # this implements all the public instance methods of the class when you use it in ruby code
107
+ # When you use it in a CLR class you're bound to CLR rules and it only overrides the methods
108
+ # that are marked as virtual. We also can't isolate static or sealed types at the moment.
109
+ class ClrIsolator < Isolator
110
+
111
+
112
+ # Implementation of the template method that creates
113
+ # an isolator for a class defined in a CLR language.
114
+ def initialize(context)
115
+ super
116
+ instance = nil
117
+ sklass = context.subject
118
+ unless context.subject.respond_to?(:class_eval)
119
+ sklass = context.subject.class
120
+ instance = context.subject
121
+ end
122
+ @descriptor = ClrClassDescriptor.new sklass
123
+ instance ||= sklass.new unless sklass.to_clr_type.is_abstract
124
+ build_isolation sklass, instance
125
+ end
126
+
127
+ # initializes the messaging strategy for the isolator
128
+ def initialize_messenger
129
+ @context.messenger = ClrClassMessenger.new @context.expectations, @subject
130
+ end
131
+
132
+ # builds the Isolator class for the specified subject
133
+ def create_isolation_for(subj)
134
+ members = @descriptor.instance_members
135
+ class_members = @descriptor.class_members
136
+ events = @descriptor.events
137
+ class_events = @descriptor.class_events
138
+
139
+ klass = Object.const_set(class_name(subj), Class.new(subj))
140
+ klass.class_eval do
141
+
142
+ include Interception
143
+
144
+ # access to the proxied subject
145
+ def ___super___
146
+ isolation_context.instance
147
+ end
148
+
149
+ def initialize(*args)
150
+ self
151
+ end
152
+
153
+ members.each do |mem|
154
+ nm = mem.name.to_s.to_sym
155
+ define_method nm do |*args|
156
+ b = nil
157
+ b = Proc.new { yield } if block_given?
158
+ isolation_context.send_message(nm, mem.return_type, *args, &b)
159
+ end unless nm == :to_string
160
+ end
161
+
162
+ class_members.each do |mn|
163
+ mn = mn.name.to_s.to_sym
164
+ define_cmethod mn do |*args|
165
+ b = nil
166
+ b = Proc.new { yield } if block_given?
167
+ isolation_context.send_class_message(mn, nil, *args, &b)
168
+ end
169
+ end
170
+
171
+ evts = (events + class_events).collect do |evt|
172
+ %w(add remove).inject("") do |res, nm|
173
+ res << <<-end_event_definition
174
+
175
+ def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
176
+ self.isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
177
+ end
178
+
179
+ end_event_definition
180
+ end
181
+
182
+ end.join("\n")
183
+
184
+ klass.class_eval evts
185
+
186
+ #puts evts
187
+
188
+ end
189
+
190
+ klass
191
+ end
192
+
193
+ end
194
+
195
+ # An +Isolator+ for CLR interfaces.
196
+ # this implements all the methods that are defined on the interface.
197
+ class ClrInterfaceIsolator < Isolator
198
+
199
+ # Implementation of the template method that creates
200
+ # an isolator for an interface defined in a CLR language.
201
+ def initialize(context)
202
+ super
203
+ sklass = context.subject
204
+ @descriptor = ClrInterfaceDescriptor.new sklass
205
+ build_isolation sklass
206
+ end
207
+
208
+ # initializes the messaging strategy for the isolator
209
+ def initialize_messenger
210
+ @context.messenger = ClrInterfaceMessenger.new @context.expectations
211
+ end
212
+
213
+ # builds the actual +isolator+ for the CLR interface
214
+ def create_isolation_for(subj)
215
+ proxy_members = @descriptor.instance_members
216
+ events = @descriptor.events
217
+
218
+ klass = Object.const_set(class_name(subj), Class.new)
219
+ klass.class_eval do
220
+
221
+ include subj
222
+ include Interception
223
+
224
+ proxy_members.each do |mem|
225
+ nm = mem.name.to_s.to_sym
226
+ define_method nm do |*args|
227
+ b = nil
228
+ b = Proc.new { yield } if block_given?
229
+ isolation_context.send_message(nm, mem.return_type, *args, &b)
230
+ end
231
+ end
232
+
233
+
234
+ end
235
+
236
+ evts = events.collect do |evt|
237
+ %w(add remove).inject("") do |res, nm|
238
+ res << <<-end_event_definition
239
+
240
+ def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
241
+ isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
242
+ end
243
+
244
+ end_event_definition
245
+ end
246
+ end.join("\n")
247
+ klass.class_eval evts
248
+
249
+ klass
250
+ end
251
+ end
252
+
253
253
  end