-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathContracts.cs
763 lines (742 loc) · 33.6 KB
/
Contracts.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
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
using DVM4T.Core.Binding;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web;
namespace DVM4T.Contracts
{
#region Tridion interfaces
public interface IHaveData //consider making this generic i.e. IHaveData<T> { T BaseData { get; } } -- would require a lot of refactoring
{
object BaseData { get; }
}
public interface ITridionItemData : IHaveData
{
string TcmUri { get; }
string Title { get; }
}
public interface IDefinedData : IViewModelData
{
ISchemaData Schema { get; }
}
public interface ITemplatedViewModelData : IViewModelData
{
/// <summary>
/// Template for the View Model
/// </summary>
ITemplateData Template { get; }
}
public interface IContentPresentationData : IDefinedData, ITemplatedViewModelData
{
IFieldsData Content { get; }
}
public interface IPageData : ITridionItemData, ITemplatedViewModelData
{
IList<IComponentPresentationData> ComponentPresentations { get; }
string FileName { get; }
}
//public interface IComponentPresentationData : ITridionItemData, IContentPresentationData //This is essentially a replacement for IComponent
//{
// IComponentData Component { get; }
// IMultimediaData MultimediaData { get; } //redundant
//}
public interface IComponentPresentationData : IContentPresentationData //This is essentially a replacement for IComponent
{
IComponentData Component { get; }
}
//Deprecated?? - use IContentPresentationData instead?
public interface IComponentData : ITridionItemData, IDefinedData, IViewModelData
{
IFieldsData Content { get; } //Slightly redundant with IContentPresentationData ...
IMultimediaData MultimediaData { get; }
}
public interface ITemplateData : ITridionItemData, IViewModelData
{
DateTime RevisionDate { get; }
}
public interface IMultimediaData : IHaveData
{
string Url { get; }
string FileName { get; }
string MimeType { get; }
}
public interface IFieldsData : IHaveData
{
IFieldData this[string key] { get; } //Convert this to xpath
bool ContainsKey(string key); //check if the XPath exists
}
public interface ISchemaData : ITridionItemData
{
string RootElementName { get; }
}
public interface ICanUseXpm
{
string XPath { get; }
string Name { get; }
string RootElementName { get; }
}
public interface IFieldData : ICanUseXpm, IHaveData
{
//The object Value is an important part of this framework -- this object will be retrieved based on the FieldAttribute's overriden method. Implementer could alternatively use the BaseData object to circumvent
/// <summary>
/// A set of Values representing the underlying value of this Field
/// </summary>
IEnumerable Values { get; } //should this be object or is it ok as Enumerable?
ISchemaData EmbeddedSchema { get; }
/// <summary>
/// The Field Type in String form
/// </summary>
string FieldTypeString { get; } //maybe make an enum?? This would prescribe the implementation though -- could use object to make it really generic
/// <summary>
/// The Keyword(s) for this Field if it is a Keyword Field. Otherwise should be null or empty.
/// </summary>
IList<IKeywordData> Keywords { get; }
}
public interface IKeywordData : ITridionItemData, IViewModelData
{
ISchemaData MetadataSchema { get; }
string Key { get; }
ICategoryData Category { get; }
}
public interface ICategoryData : ITridionItemData
{
string XmlName { get; }
}
#endregion
/// <summary>
/// A View Model
/// </summary>
public interface IViewModel
{
/// <summary>
/// Consolidated data for this View Model
/// </summary>
IViewModelData ModelData { get; set; }
}
/// <summary>
/// View Model Data - the basic data that all View Models have
/// </summary>
public interface IViewModelData : IHaveData //Should this extend IHaveData? I don't think so at this time because each piece i.e. Content, MetadataFields has their own BaseData object
{
/// <summary>
/// The underlying data object that the View Model represents
/// </summary>
//IViewModelFactory Builder { get; } //This isn't actually needed anywhere -- should it remane for lazy loading? probably not because there should always be a way to access the factory
/// <summary>
/// Metadata for the View Model
/// </summary>
IFieldsData Metadata { get; }
/// <summary>
/// Publication ID of the underlying Tridion item
/// </summary>
int PublicationId { get; }
}
/// <summary>
/// A Resolver for View Models and Model Properties
/// </summary>
public interface IViewModelResolver
{
/// <summary>
/// Resolves an instance of a View Model of the given Type
/// </summary>
/// <param name="type">View Model Type to resolve</param>
/// <param name="data">View Model Data for context</param>
/// <returns>An instance of a View Model of the input Type</returns>
IViewModel ResolveModel(Type type, IViewModelData data);
/// <summary>
/// Gets a list of Model Property objects for all Properties marked with an IPropertyAttribute Attribute for the given Type
/// </summary>
/// <param name="type">Type with the Properties to search</param>
/// <returns>List of Model Properties</returns>
IList<IModelProperty> GetModelProperties(Type type);
/// <summary>
/// Gets a single Model Property object
/// </summary>
/// <param name="propertyInfo">Property Info to build a Model Property object for</param>
/// <returns>Model Property</returns>
IModelProperty GetModelProperty(PropertyInfo propertyInfo);
/// <summary>
/// Gets a single Model Property object
/// </summary>
/// <typeparam name="TSource">Type of the Model</typeparam>
/// <typeparam name="TProperty">Type of the Property</typeparam>
/// <param name="source">Object for inferring TSource</param>
/// <param name="propertyLambda">Lambda Expression for the property to build a Model Property object for</param>
/// <returns>Model Property</returns>
IModelProperty GetModelProperty<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> propertyLambda);
/// <summary>
/// Gets a single Model Property object
/// </summary>
/// <typeparam name="TSource">Type of the Model</typeparam>
/// <typeparam name="TProperty">Type of the Property</typeparam>
/// <param name="propertyLambda">Lambda Expression for the property to build a Model Property object for</param>
/// <returns>Model Property</returns>
IModelProperty GetModelProperty<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda);
/// <summary>
/// Gets a specfic Model Attribute in the given Type
/// </summary>
/// <typeparam name="T">Type of Model Attribute to look for</typeparam>
/// <param name="type">Type to search</param>
/// <returns>A Model Attribute</returns>
T GetCustomAttribute<T>(Type type) where T : IModelAttribute;
/// <summary>
/// Gets a model property based on property info and a property attribute
/// </summary>
/// <param name="propertyInfo">Property</param>
/// <param name="attribute">Associated attribute</param>
/// <returns>Model property</returns>
IModelProperty GetModelProperty(PropertyInfo propertyInfo, IPropertyAttribute attribute);
/// <summary>
/// Gets a model property based on lambda expression for a property and a property attribute
/// </summary>
/// <typeparam name="TModel">Model type</typeparam>
/// <typeparam name="TProperty">Property type</typeparam>
/// <param name="propertyLambda">Lambda expression representing the property</param>
/// <param name="attribute">Associated attribute</param>
/// <returns>Model property</returns>
IModelProperty GetModelProperty<TModel, TProperty>(Expression<Func<TModel, TProperty>> propertyLambda, IPropertyAttribute attribute);
/// <summary>
/// Resolves a new instance based on the input Type.
/// </summary>
/// <param name="type">Type to create or use to determine object to return.</param>
/// <returns>New instance</returns>
object ResolveInstance(Type type);
/// <summary>
/// Resolves a new instance based on the input Type.
/// </summary>
/// <typeparam name="T">Type to create or use to determine object to return.</typeparam>
/// <param name="ctorArgs">Optional constructor arguments</param>
/// <returns>New instance</returns>
T ResolveInstance<T>(params object[] ctorArgs);
/// <summary>
/// The associate reflection helper
/// </summary>
IReflectionHelper ReflectionHelper { get; }
}
/// <summary>
/// A Factory for building View Models with input base data
/// </summary>
public interface IViewModelFactory
{
/// <summary>
/// Loads all View Model classes from an assembly.
/// </summary>
/// <param name="assemblies">The Assemblies with the view model Types to load</param>
/// <remarks>
/// Required for use of builder methods that don't require a Type parameter or generic.
/// The Builder will only use Types tagged with an IModelAttribute Attribute.
/// </remarks>
void LoadViewModels(params Assembly[] assemblies);
/// <summary>
/// Finds a View Model with the specified Type using the input Data.
/// </summary>
/// <typeparam name="T">Type of View Model Attribute</typeparam>
/// <param name="data">View Model Data to search for</param>
/// <param name="typesToSearch">Optional array of possible Types to search through</param>
/// <returns>View Model Type</returns>
Type FindViewModelByAttribute<T>(IViewModelData data, Type[] typesToSearch = null) where T : IModelAttribute;
/// <summary>
/// Sets the value of a single Model Property
/// </summary>
/// <param name="model">View Model</param>
/// <param name="data">Model data</param>
/// <param name="property">Property to set</param>
void SetPropertyValue(object model, IViewModelData data, IModelProperty property);
/// <summary>
/// Sets the value of a single Model Property
/// </summary>
/// <param name="model">View Model</param>
/// <param name="property">Property to set</param>
void SetPropertyValue(IViewModel model, IModelProperty property);
/// <summary>
/// Sets the value of a single Model Property
/// </summary>
/// <typeparam name="TModel">Type of View Model</typeparam>
/// <typeparam name="TProperty">Type of Property</typeparam>
/// <param name="model">View Model</param>
/// <param name="propertyLambda">Lambda Expression for Property to set</param>
void SetPropertyValue<TModel, TProperty>(TModel model, Expression<Func<TModel, TProperty>> propertyLambda) where TModel : IViewModel;
/// <summary>
/// Builds a View Model, inferring the Type based on the Model Data.
/// </summary>
/// <param name="modelData">Model Data</param>
/// <returns>A View Model</returns>
/// <remarks>Requires LoadViewModels to have been used.</remarks>
IViewModel BuildViewModel(IViewModelData modelData);
/// <summary>
/// Builds a View Model, inferring the Type based on the Model Data and filtering possible Model Types by an Attribute.
/// </summary>
/// <typeparam name="T">The Model Attribute to filter Model Types by</typeparam>
/// <param name="modelData">Model Data</param>
/// <returns>View Model</returns>
/// <remarks>
/// One can use a Model Attribute Type to filter to only certain types of models such as Page Models
/// or Keyword Models to increase performance.
/// Requires LoadViewModels to have been used.
/// </remarks>
IViewModel BuildViewModelByAttribute<T>(IViewModelData modelData) where T : IModelAttribute;
/// <summary>
/// Builds a View Model of the specified type.
/// </summary>
/// <param name="type">Specific type of View Model to build - must implement IViewModel</param>
/// <param name="modelData">Model Data</param>
/// <returns>View Model</returns>
IViewModel BuildViewModel(Type type, IViewModelData modelData); //Does this need to be publicly exposed?
/// <summary>
/// Builds a View Model of the specified type.
/// </summary>
/// <typeparam name="T">Specific type of View Model to build</typeparam>
/// <param name="modelData">Model Data</param>
/// <returns>View Model</returns>
T BuildViewModel<T>(IViewModelData modelData) where T : IViewModel;
/*Anyway to move these to separate Binding library? Appears not because IPropertyAttribute is dependent on IModelMapping and all
* GetPropertyValues are only passed a IViewModelFactory so there's no other way to access the Mapped Model methods
*/
/// <summary>
/// Builds a model using a specific mapping
/// </summary>
/// <typeparam name="T">Model Type</typeparam>
/// <param name="model">Model to populate</param>
/// <param name="modelData">Model Data</param>
/// <param name="mapping">Model Mapping</param>
/// <returns>Fully built model</returns>
T BuildMappedModel<T>(T model, IViewModelData modelData, IModelMapping mapping); //where T : class;
/// <summary>
/// Builds a new model using a specific mapping
/// </summary>
/// <typeparam name="T">Model Type</typeparam>
/// <param name="modelData">Model Data</param>
/// <param name="mapping">Model Mapping</param>
/// <returns>New model</returns>
T BuildMappedModel<T>(IViewModelData modelData, IModelMapping mapping); //where T : class;
/// <summary>
/// Builds a new model using a specific mapping
/// </summary>
/// <param name="modelData">Model data</param>
/// <param name="mapping">Model mapping</param>
/// <returns>New model</returns>
object BuildMappedModel(IViewModelData modelData, IModelMapping mapping);
/// <summary>
/// The associate model resolver for this instance
/// </summary>
IViewModelResolver ModelResolver { get; }
}
public interface IXpmMarkupService
{
/// <summary>
/// Renders the XPM Markup for a field
/// </summary>
/// <param name="field">Tridion Field</param>
/// <param name="index">Optional index for multi value fields</param>
/// <returns>XPM Markup</returns>
string RenderXpmMarkupForField(IFieldData field, int index = -1);
/// <summary>
/// Renders the XPM Markup for a Component Presentation
/// </summary>
/// <param name="cp">Component Presentation</param>
/// <param name="region">Optional region</param>
/// <returns>XPM Markup</returns>
string RenderXpmMarkupForComponent(IComponentPresentationData cp, string region = null);
/// <summary>
/// Determines if Site Edit is enabled for a particular item
/// </summary>
/// <param name="item">Item</param>
/// <returns></returns>
bool IsSiteEditEnabled(ITridionItemData item);
/// <summary>
/// Determines if Site Edit is enabeld for a publication
/// </summary>
/// <param name="publicationId">Publication ID</param>
/// <returns></returns>
bool IsSiteEditEnabled(int publicationId);
}
/// <summary>
/// An object that renders XPM Markup for a specific Model
/// </summary>
/// <typeparam name="TModel">Type of Model</typeparam>
public interface IXpmRenderer<TModel> where TModel : IViewModel
{
/// <summary>
/// Renders both XPM Markup and Field Value
/// </summary>
/// <typeparam name="TModel">Model type</typeparam>
/// <typeparam name="TProp">Property type</typeparam>
/// <param name="model">Model</param>
/// <param name="propertyLambda">Lambda expression representing the property to render. This must be a direct property of the model.</param>
/// <param name="index">Optional index for a multi-value field</param>
/// <returns>XPM Markup and field value</returns>
HtmlString XpmEditableField<TProp>(Expression<Func<TModel, TProp>> propertyLambda, int index = -1);
/// <summary>
/// Renders both XPM Markup and Field Value for a multi-value field
/// </summary>
/// <typeparam name="TModel">Model type</typeparam>
/// <typeparam name="TProp">Property type</typeparam>
/// <typeparam name="TItem">Item type - this must match the generic type of the property type</typeparam>
/// <param name="model">Model</param>
/// <param name="propertyLambda">Lambda expression representing the property to render. This must be a direct property of the model.</param>
/// <param name="item">The particular value of the multi-value field</param>
/// <example>
/// foreach (var content in model.Content)
/// {
/// @model.XpmEditableField(m => m.Content, content);
/// }
/// </example>
/// <returns>XPM Markup and field value</returns>
HtmlString XpmEditableField<TProp, TItem>(Expression<Func<TModel, TProp>> propertyLambda, TItem item);
/// <summary>
/// Renders the XPM markup for a field
/// </summary>
/// <typeparam name="TModel">Model type</typeparam>
/// <typeparam name="TProp">Property type</typeparam>
/// <param name="model">Model</param>
/// <param name="propertyLambda">Lambda expression representing the property to render. This must be a direct property of the model.</param>
/// <param name="index">Optional index for a multi-value field</param>
/// <returns>XPM Markup</returns>
HtmlString XpmMarkupFor<TProp>(Expression<Func<TModel, TProp>> propertyLambda, int index = -1);
/// <summary>
/// Renders XPM Markup for a multi-value field
/// </summary>
/// <typeparam name="TModel">Model type</typeparam>
/// <typeparam name="TProp">Property type</typeparam>
/// <typeparam name="TItem">Item type - this must match the generic type of the property type</typeparam>
/// <param name="model">Model</param>
/// <param name="propertyLambda">Lambda expression representing the property to render. This must be a direct property of the model.</param>
/// <param name="item">The particular value of the multi-value field</param>
/// <example>
/// foreach (var content in model.Content)
/// {
/// @model.XpmMarkupFor(m => m.Content, content);
/// @content;
/// }
/// </example>
/// <returns>XPM Markup</returns>
HtmlString XpmMarkupFor<TProp, TItem>(Expression<Func<TModel, TProp>> propertyLambda, TItem item);
/// <summary>
/// Renders the XPM Markup for a Component Presentation
/// </summary>
/// <param name="model">Model</param>
/// <param name="region">Region</param>
/// <returns>XPM Markup</returns>
HtmlString StartXpmEditingZone(string region = null);
}
/// <summary>
/// Provides the View Model Key using a Component Template
/// </summary>
public interface IViewModelKeyProvider
{
/// <summary>
/// Retrieves a View Model Key based on a Component Template. Should return the same key for the same template every time.
/// Return values of null or empty string will be ignored.
/// </summary>
/// <param name="model">View Model Data to retrieve a key for</param>
/// <returns>View Model Key</returns>
string GetViewModelKey(IViewModelData model);
}
/// <summary>
/// Object can be a Boolean
/// </summary>
public interface ICanBeBoolean
{
/// <summary>
/// True to return a boolean value
/// </summary>
bool IsBooleanValue { get; set; }
}
/// <summary>
/// A set of methods for performing Reflection-related functions
/// </summary>
public interface IReflectionHelper
{
/// <summary>
/// Creates an instance of an object
/// </summary>
/// <param name="objectType">Type of object to create</param>
/// <returns>Object of the Type specified</returns>
object CreateInstance(Type objectType);
/// <summary>
/// Creates an instance of an object
/// </summary>
/// <typeparam name="T">Type of object to create</typeparam>
/// <returns>Object of the Type specified</returns>
T CreateInstance<T>() where T : class, new();
/// <summary>
/// Builds a Setter delegate for the given Property
/// </summary>
/// <param name="propertyInfo">Property - must have a Set method</param>
/// <returns>Setter delegate action</returns>
Action<object, object> BuildSetter(PropertyInfo propertyInfo);
/// <summary>
/// Builds a Getter delegate for a given Prpoerty
/// </summary>
/// <param name="propertyInfo">Property</param>
/// <returns>Getter delegate function</returns>
Func<object, object> BuildGetter(PropertyInfo propertyInfo);
/// <summary>
/// Gets the PropertyInfo for a Lambda Expression
/// </summary>
/// <typeparam name="TSource">The source Type</typeparam>
/// <typeparam name="TProperty">The property Type</typeparam>
/// <param name="propertyLambda">Lambda Expression representing a Property of the source Type</param>
/// <returns>Property Info</returns>
PropertyInfo GetPropertyInfo<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda);
/// <summary>
/// Gets the PropertyInfo for a Lambda Expression
/// </summary>
/// <param name="source">Source object - for type inferrence of the Lambda Expression</param>
/// <typeparam name="TSource">The source Type</typeparam>
/// <typeparam name="TProperty">The property Type</typeparam>
/// <param name="propertyLambda">Lambda Expression representing a Property of the source Type</param>
/// <returns>Property Info</returns>
PropertyInfo GetPropertyInfo<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> propertyLambda);
/// <summary>
/// Builds a delegate from the Add method of a collection. The input Type must implement ICollection<>
/// </summary>
/// <typeparam name="TCollection">Type of collection. Must implement ICollection<></param>
/// <returns>Delegate function that takes two parameters: the collection and the item to add to it.</returns>
Action<object, object> BuildAddMethod<TCollection>();
/// <summary>
/// Builds a delegate from the Add method of a collection. The input Type must implement ICollection<>
/// </summary>
/// <param name="collectionType">Type of collection. Must implement ICollection<></param>
/// <returns>Delegate function that takes two parameters: the collection and the item to add to it.</returns>
Action<object, object> BuildAddMethod(Type collectionType);
/// <summary>
/// Determines if a type is a generic collection (ICollection<T>)
/// </summary>
/// <param name="type">Type to inspect</param>
/// <param name="genericType">Returns the Generic type T for ICollection<T>, otherwise it is null</param>
/// <returns>True if this is a generic collection</returns>
bool IsGenericCollection(Type type, out Type genericType);
/// <summary>
/// Determines if a type is an Array
/// </summary>
/// <param name="type">Array to inspect</param>
/// <param name="elementType">Returns a single element's Type if this is an array, otherwise null.</param>
/// <returns>True if this is an Array.</returns>
bool IsArray(Type type, out Type elementType);
/// <summary>
/// Determines if a type is an enumerable (IEnumerable)
/// </summary>
/// <param name="type">Type to inspect</param>
/// <returns>True is this is an enumerable</returns>
bool IsEnumerable(Type type);
/// <summary>
/// Builds a re-usable function for converting an IEnumerable to an Array.
/// </summary>
/// <remarks>Useful when the generic type of IEnumerable is unknown at compile time.</remarks>
/// <param name="elementType">Single element type of the array</param>
/// <returns>Function for converting an IEnumerable to an Array</returns>
Func<IEnumerable, Array> BuildToArray(Type elementType);
}
/// <summary>
/// A simple representation of a Model Property
/// </summary>
public interface IModelProperty
{
/// <summary>
/// Name of the Property
/// </summary>
string Name { get; }
/// <summary>
/// Setter delegate
/// </summary>
Action<object, object> Set { get; }
/// <summary>
/// Getter delegate
/// </summary>
Func<object, object> Get { get; }
/// <summary>
/// The DVM4T PropertyAttribute of the Property
/// </summary>
IPropertyAttribute PropertyAttribute { get; }
/// <summary>
/// The return Type of the Property
/// </summary>
Type PropertyType { get; }
/// <summary>
/// The type of a single model, which is not the same as property type for multi-value properties
/// </summary>
Type ModelType { get; }
/// <summary>
/// Is this property an enumerable type
/// </summary>
bool IsEnumerable { get; }
/// <summary>
/// Is this property a Collection
/// </summary>
bool IsCollection { get; }
/// <summary>
/// Is this property an Array
/// </summary>
bool IsArray { get; }
/// <summary>
/// Re-usable action delegate for adding individual items to a collection
/// </summary>
Action<object, object> AddToCollection { get; }
/// <summary>
/// Re-usable action for converting a non-Generic IEnumerable to an Array
/// </summary>
Func<IEnumerable, Array> ToArray { get; }
}
/// <summary>
/// An attribute for a Property of a View Model
/// </summary>
public interface IPropertyAttribute
{
/// <summary>
/// The expected return type for this Property
/// </summary>
Type ExpectedReturnType { get; }
/// <summary>
/// Gets the value for this property based on a View Model data object
/// </summary>
/// <param name="model">View Model this Property is in</param>
/// <param name="propertyType">Actual return type of the Property</param>
/// <param name="builder">A View Model Builder</param>
/// <returns>Property value</returns>
IEnumerable GetPropertyValues(IViewModelData modelData, IModelProperty property, IViewModelFactory builder = null); //Strongly consider offloading some of the work to IModelProperty -- e.g. IsMultiValue, AddToCollection, etc.
/// <summary>
/// Optional mapping if the Property is a Complex Type. This should only set by a Binding Module.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
IModelMapping ComplexTypeMapping { get; set; } //Anyway to get this dependency on the Binding namespace out?
}
/// <summary>
/// An attribute for a Property representing a Field
/// </summary>
public interface IFieldAttribute : IPropertyAttribute
{
/// <summary>
/// Get the value of a Field
/// </summary>
/// <param name="field">Field for this property</param>
/// <param name="propertyType">Actual return type of this Property</param>
/// <param name="template">A Template for context</param>
/// <param name="builder">A View Model builder</param>
/// <returns>Property value</returns>
IEnumerable GetFieldValues(IFieldData field, IModelProperty property, ITemplateData template,IViewModelFactory builder = null);
/// <summary>
/// Schema XML name of the Field
/// </summary>
string FieldName { get; }
/// <summary>
/// If true, this Field is multi-value
/// </summary>
bool AllowMultipleValues { get; }
/// <summary>
/// Inline Editable - for semantic purposes only
/// </summary>
bool InlineEditable { get; }
/// <summary>
/// Is Mandatory - for semantic purposes only
/// </summary>
bool Mandatory { get; }
/// <summary>
/// True if this is a Metadata Field of the Model
/// </summary>
bool IsMetadata { get; }
/// <summary>
/// True if this is a Metadata Field of the Template of the Model
/// </summary>
bool IsTemplateMetadata { get; }
}
//TODO: Use these interfaces in the builder
/// <summary>
/// An Attribute for a Property representing some part of a Component
/// </summary>
public interface IComponentAttribute : IPropertyAttribute
{
/// <summary>
/// Gets a value for this Property based on a Component
/// </summary>
/// <param name="contentPresentation">The Component object for this Model</param>
/// <param name="propertyType">The actual return type of this Property</param>
///
/// <param name="builder">A View Model builder</param>
/// <returns>The Property value</returns>
IEnumerable GetPropertyValues(IComponentData component, IModelProperty property, ITemplateData template, IViewModelFactory builder = null);
}
/// <summary>
/// An Attribtue for a Property representing some part of a Component Template
/// </summary>
public interface ITemplateAttribute : IPropertyAttribute
{
/// <summary>
/// Gets a value for this Property based on a Component Template
/// </summary>
/// <param name="template">The Template for this Model</param>
/// <param name="propertyType">The actual return type of this Property</param>
/// <param name="builder">A View Model builder</param>
/// <returns>The Property value</returns>
object GetPropertyValues(ITemplateData template, Type propertyType, IViewModelFactory builder = null);
}
/// <summary>
/// An Attribute for a Property representing some part of a Page
/// </summary>
public interface IPageAttribute : IPropertyAttribute
{
/// <summary>
/// Gets a value for this Property based on a Page
/// </summary>
/// <param name="page">The Template for this Model</param>
/// <param name="propertyType">The actual return type of this Property</param>
/// <param name="builder">A View Model builder</param>
/// <returns>The Property value</returns>
object GetPropertyValues(IPageData page, Type propertyType, IViewModelFactory builder = null);
}
/// <summary>
/// An Attribute for identifying a View Model class
/// </summary>
public interface IModelAttribute
{
/// <summary>
/// View Model Keys - a set of identifying values for this Model
/// </summary>
string[] ViewModelKeys { get; set; }
/// <summary>
/// Checks if this Model is a match for a specific View Model Data
/// </summary>
/// <param name="data">View Model Data to compare</param>
/// <param name="key">View Model Key</param>
/// <returns>True if it matches, false if not</returns>
bool IsMatch(IViewModelData data, string key);
}
/// <summary>
/// An Attribute for identifying a Defined (has a Schema) View Model class
/// </summary>
public interface IDefinedModelAttribute : IModelAttribute
{
/// <summary>
/// XML Name of the Schema
/// </summary>
string SchemaName { get; }
/// <summary>
/// Is Inline Editable - for semantic purposes only
/// </summary>
[Obsolete]
bool InlineEditable { get; set; }
/// <summary>
/// Is this the default Model for this Schema
/// </summary>
bool IsDefault { get; }
}
/// <summary>
/// An Attribute for identifying a Page Model class
/// </summary>
public interface IPageModelAttribute : IModelAttribute
{
//What Properties go here to identify a Page Model?
}
/// <summary>
/// An Attribute for identifying a Keyword Model class
/// </summary>
public interface IKeywordModelAttribute : IModelAttribute
{
//Anything?
}
}