-
Notifications
You must be signed in to change notification settings - Fork 275
/
Examples.cs
440 lines (350 loc) · 12.4 KB
/
Examples.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Forms;
using StructureMap.Attributes;
using StructureMap.Configuration.DSL;
using StructureMap.Testing.Widget3;
namespace StructureMap.Testing.DocumentationExamples
{
public interface IDataProvider
{
}
public class Repository
{
private IDataProvider _provider;
// Adding the SetterProperty to a setter directs
// StructureMap to use this property when
// constructing a Repository instance
[SetterProperty]
public IDataProvider Provider { set { _provider = value; } }
[SetterProperty]
public bool ShouldCache { get; set; }
}
public interface IShippingService
{
void ShipIt();
}
public class ShippingWebService : IShippingService
{
private readonly string _url;
public ShippingWebService(string url)
{
_url = url;
}
public void ShipIt()
{
throw new NotImplementedException();
}
}
public class InternalShippingService : IShippingService
{
public void ShipIt()
{
throw new NotImplementedException();
}
}
public class ShippingRegistry : Registry
{
public ShippingRegistry()
{
ForRequestedType<IShippingService>().AddInstances(x =>
{
x.OfConcreteType<ShippingWebService>()
.WithCtorArg("url").EqualTo("a url")
.WithName("Domestic");
x.OfConcreteType<ShippingWebService>()
.WithCtorArg("url").EqualTo("a different url")
.WithName("International");
x.OfConcreteType<InternalShippingService>().WithName("Internal");
});
}
}
public class ClassThatUsesShippingService
{
public ClassThatUsesShippingService()
{
// Accessing the IShippingService Instance's by name
var internationalService = ObjectFactory.GetNamedInstance<IShippingService>("International");
var domesticService = ObjectFactory.GetNamedInstance<IShippingService>("Domestic");
var internalService = ObjectFactory.GetNamedInstance<IShippingService>("Internal");
// Without generics
var internationalService2 =
(IShippingService) ObjectFactory.GetNamedInstance(typeof (IShippingService), "International");
internationalService.ShipIt();
domesticService.ShipIt();
internationalService2.ShipIt();
string serviceName = determineShippingService();
var service = ObjectFactory.GetNamedInstance<IShippingService>(serviceName);
service.ShipIt();
}
private string determineShippingService()
{
throw new NotImplementedException();
}
// With Generics
public ValidationResult RunRulesWithGenerics(Invoice invoice)
{
var result = new ValidationResult();
IList<InvoiceValidator> validators = ObjectFactory.GetAllInstances<InvoiceValidator>();
foreach (InvoiceValidator validator in validators)
{
validator.Validate(invoice, result);
}
return result;
}
// Without Generics
public ValidationResult RunRulesWithoutGenerics(Invoice invoice)
{
var result = new ValidationResult();
IList validators = ObjectFactory.GetAllInstances(typeof (InvoiceValidator));
foreach (InvoiceValidator validator in validators)
{
validator.Validate(invoice, result);
}
return result;
}
#region Nested type: InvoiceValidator
public interface InvoiceValidator
{
void Validate(Invoice invoice, ValidationResult result);
}
#endregion
#region Nested type: ValidationResult
public class ValidationResult
{
}
#endregion
}
public class ScanningRegistry : Registry
{
public ScanningRegistry()
{
Scan(x =>
{
// Add assembly by name.
x.Assembly("StructureMap.Testing.Widget");
// Add an assembly directly
x.Assembly(Assembly.GetExecutingAssembly());
// Add the assembly that contains a certain type
x.AssemblyContainingType<IService>();
// or
x.AssemblyContainingType(typeof (IService));
});
Scan(x =>
{
// I'm telling StructureMap to sweep a folder called "Extensions" directly
// underneath the application root folder for any assemblies
x.AssembliesFromPath("Extensions");
// I also direct StructureMap to add any Registries that it finds in these
// assemblies. I'm assuming that all the StructureMap directives are
// contained in Registry classes -- and this is the recommended approach
x.LookForRegistries();
});
Scan(x =>
{
// This time I'm going to specify a filter on the assembly such that
// only assemblies that have "Extension" in their name will be scanned
x.AssembliesFromPath("Extensions", assembly => assembly.GetName().Name.Contains("Extension"));
x.LookForRegistries();
});
// Adding configuration from an extension Assembly
// after ObjectFactory is already configured
ObjectFactory.Configure(x =>
{
x.Scan(scan =>
{
scan.Assembly("MyCompany.MyApp.ExtensionAssembly");
scan.LookForRegistries();
});
});
}
}
public class Invoice
{
}
public interface IRepository
{
}
public interface IPresenter
{
void Activate();
}
public class ShippingScreenPresenter : IPresenter
{
private readonly IRepository _repository;
private readonly IShippingService _service;
// This is the way to write a Constructor Function with an IoC tool
// Let the IoC container "inject" services from outside, and keep
// ShippingScreenPresenter ignorant of the IoC infrastructure
public ShippingScreenPresenter(IShippingService service, IRepository repository)
{
_service = service;
_repository = repository;
}
// FAIL!
// This is the wrong way to use an IoC container. Do NOT invoke the container from
// the constructor function. This tightly couples the ShippingScreenPresenter to
// the IoC container in a harmful way. This class cannot be used in either
// production or testing without a valid IoC configuration. Plus, you're writing more
// code
public ShippingScreenPresenter()
{
_service = ObjectFactory.GetInstance<IShippingService>();
_repository = ObjectFactory.GetInstance<IRepository>();
}
#region IPresenter Members
public void Activate()
{
}
#endregion
}
public class ApplicationController
{
public void ActivateScreenFor<T>() where T : IPresenter
{
IPresenter presenter = ObjectFactory.GetInstance<T>();
presenter.Activate();
}
public void ActivateScreen(IPresenter presenter)
{
}
}
public class Navigates
{
public Navigates()
{
// You most certainly do NOT just new() up an ApplicationController
var controller = ObjectFactory.GetInstance<ApplicationController>();
controller.ActivateScreenFor<ShippingScreenPresenter>();
}
}
public interface IEditInvoiceView
{
}
public class EditInvoicePresenter : IPresenter
{
private readonly Invoice _invoice;
private readonly IRepository _repository;
private readonly IEditInvoiceView _view;
public EditInvoicePresenter(IRepository repository, IEditInvoiceView view, Invoice invoice)
{
_repository = repository;
_view = view;
_invoice = invoice;
}
#region IPresenter Members
public void Activate()
{
}
#endregion
private void editInvoice(Invoice invoice, ApplicationController controller)
{
var presenter = ObjectFactory.With(invoice).GetInstance<EditInvoicePresenter>();
controller.ActivateScreen(presenter);
}
}
public interface IApplicationShell
{
}
//IQueryToolBar or IExplorerPane
public interface IQueryToolBar
{
}
public interface IExplorerPane
{
}
public class ApplicationShell : Form, IApplicationShell
{
public IQueryToolBar QueryToolBar { get { return null; } }
public IExplorerPane ExplorerPane { get { return null; } }
}
public class QueryController
{
private IQueryToolBar _toolBar;
public QueryController(IQueryToolBar toolBar)
{
_toolBar = toolBar;
}
}
public class InjectionClass
{
public InjectionClass()
{
// Familiar stuff for the average WinForms or WPF developer
// Create the main form
var shell = new ApplicationShell();
// Put the main form, and some of its children into StructureMap
// where other Controllers and Commands can get to them
// without being coupled to the main form
ObjectFactory.Inject<IApplicationShell>(shell);
ObjectFactory.Inject(shell.QueryToolBar);
ObjectFactory.Inject(shell.ExplorerPane);
Application.Run(shell);
}
}
public class Bootstrapper : IBootstrapper
{
private static bool _hasStarted;
public void BootstrapStructureMap()
{
ObjectFactory.Initialize(x =>
{
// initialization
});
}
public static void Restart()
{
if (_hasStarted)
{
ObjectFactory.ResetDefaults();
}
else
{
Bootstrap();
_hasStarted = true;
}
}
public static void Bootstrap()
{
new Bootstrapper().BootstrapStructureMap();
}
}
public static class Program
{
[STAThread]
public static void Main(params string[] args)
{
}
}
public class RemoteService : IService
{
public void DoSomething()
{
throw new NotImplementedException();
}
}
public class InstanceExampleRegistry : Registry
{
public InstanceExampleRegistry()
{
// Shortcut for just specifying "use this type -- with auto wiring"
ForRequestedType<IService>().TheDefaultIsConcreteType<RemoteService>();
// Set the default Instance of a PluginType
For<IService>().Use<RemoteService>();
// Add an additional Instance of a PluginType
InstanceOf<IService>().Is.OfConcreteType<RemoteService>();
// Add multiple additional Instances of a PluginType
ForRequestedType<IService>().AddInstances(x =>
{
x.ConstructedBy(() => new ColorService("Red"));
x.OfConcreteType<RemoteService>();
x.Object(new ColorService("Red"));
});
// Use the InstanceExpression to define the default Instance
// of a PluginType within a Profile
Profile("Connected", x => { x.Type<IService>().Is.OfConcreteType<RemoteService>(); });
}
}
}