-
SubjectToday we add methods on both our model classes as or model collection classes and we do that in two manners:
Question: should we standardize on extension methods for everything except "Add..." methods? This would give contributors an easy and consistent approach for "enriching" the model. I don't see a ton of value in having the methods appear in the interfaces + this also allows to easier split up the code. One can even argue if all methods on the model should be implemented as extension methods?? Tagging @PaoloPia , @ypcode , @pkbullock and @JarbasHorst for input. SamplesModel methodsInterface sample. IWeb.cs: public Task<IFolder> GetFolderByServerRelativeUrlAsync(string serverRelativeUrl,
params Expression<Func<IFolder, object>>[] expressions); and web.cs: public async Task<IFolder> GetFolderByServerRelativeUrlAsync(string serverRelativeUrl,
params Expression<Func<IFolder, object>>[] expressions)
{
Folder folder = new Folder()
{
PnPContext = this.PnPContext,
Parent = this
};
await folder.BaseGet(apiOverride: BuildGetFolderByRelativeUrlApiCall(serverRelativeUrl),
fromJsonCasting: folder.MappingHandler, postMappingJson: folder.PostMappingHandler,
expressions: expressions).ConfigureAwait(false);
return folder;
} Extension method sample. WebExtensions.cs: public static async Task<bool> IsNoScriptSiteAsync(this IWeb web)
{
await web.EnsurePropertiesAsync(w => w.EffectiveBasePermissions).ConfigureAwait(false);
// Definition of no-script is not having the AddAndCustomizePages permission
if (!web.EffectiveBasePermissions.Has(PermissionKind.AddAndCustomizePages))
{
return true;
}
return false;
} Model collection methodsInterface sample. IRecycleBinItemCollection.cs: public Task RestoreAllAsync(); and recyclebinitemcollection.cs: public async Task RestoreAllAsync()
{
var item = new RecycleBinItem()
{
PnPContext = PnPContext,
Parent = Parent
};
var entity = EntityManager.GetClassInfo(item.GetType(), item);
string deleteAllEndpointUrl = $"{entity.SharePointGet}/RestoreAll()";
var apiCall = new ApiCall(deleteAllEndpointUrl, ApiType.SPORest);
await item.RawRequestAsync(apiCall, HttpMethod.Post).ConfigureAwait(false);
} Extension method sample. RecycleBinItemExtensions.cs: public static IRecycleBinItem GetById(this IQueryable<IRecycleBinItem> source, Guid id,
params Expression<Func<IRecycleBinItem, object>>[] selectors)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
return BaseDataModelExtensions.BaseLinqGet(source, l => l.Id == id, selectors);
} |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
So I haven't done much on the old sites core but as far as I understand this is predominantly extension based which the existing developers understood - so thinking that keeping an element of familiarity in the implementation would help those currently contributing on that repo to move over. Sounds like you have a direction in mind, sorry I cannot offer a more technical reason either way. |
Beta Was this translation helpful? Give feedback.
-
IMHO, it might indeed help with more concise and clear way to extend a model and would avoid cumbersome task of adding the signature in one place and implementation on another. If technically, there is no impact on performance (I don't know if it works any differently in CLR for extensions or member methods ?). Then I don't see any technical reasons not to go this way :) However, 1 thing I would be a bit concerned about is the generated documentation... As a consumer of the SDK I would like to see at once all the methods available and not having to go to 2 documentation sources for the available methods of a same entity... (Based on what we figured out, DocFX is referencing the available extensions methods but redirect to other pages for more details). I know that VS intellisense will give me everything... :D but I would think we would need the official docs to be clear enough and not to rely of developers editors |
Beta Was this translation helpful? Give feedback.
-
That's indeed an interesting discussion. However, I'm not in favor of moving from interface and instance methods to extensions methods. There are multiple reasons supporting my previous sentence. Let me try to explain the reasoning behind.
Performances are not a real problem, because under the cover extension methods and instance methods perform almost the same. Actually, extension method are on average a little bit slower than instance methods, but it is really a tiny difference that I wouldn’t care of. So, to wrap up … that’s why I’m not in favor of replacing instance methods with extension methods and I would keep on writing the domain model the right way, using the correct OOP patterns. Sorry for the long reply, but I wanted to be clear (hopefully). |
Beta Was this translation helpful? Give feedback.
-
Very clear and well written arguments @PaoloPia. The main reason why I brought this up is consistency, today we've a mix of both which is confusing for developers. With your above arguments in mind let's then standardize on regular methods and rewrite the existing model extension methods to regular methods. |
Beta Was this translation helpful? Give feedback.
That's indeed an interesting discussion. However, I'm not in favor of moving from interface and instance methods to extensions methods. There are multiple reasons supporting my previous sentence. Let me try to explain the reasoning behind.