caricature 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
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