Standard Methods vs Extensions Methods - c#

Assuming the following domain entity :
public enum Role
{
User = 0,
Moderator = 1,
Administrator = 2
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
}
I need to know if the user can perform "Edit" action. So i've 2 solutions :
Create a CanEdit method inside the User entity
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
public bool CanEdit()
{
return Role == Role.Moderator || Role == Role.Administrator;
}
}
Create a CanEdit Extension Method for User type :
public static class UserExtensions
{
public static bool CanEdit(this User user)
{
return user.Role == Role.Moderator || user.Role == Role.Administrator;
}
}
Both solution works, but the question is WHEN use standard methods vs using Extensions methods ?

Extension methods are simply syntactic sugar for plain, ordinary static methods.
If you control the class structure, you should implement all the necessary functionality within the class. Where extension methods are really useful/necessary is if you don't own the class that you are trying to "extend."
For this example, I think you should put the logic inside the User class. It is a logical function of the user itself; consumers should be able to use the CanEdit() method without having to use or even know about the UserExtensions class.

I mostly agree with Aaronaught's answer, but consider this:
Maybe your CanEdit() method or other similar methods (business rules) might change more or less often or depend on some external factors. Or over time, you will have more and more such rules (for different concerns). In that case you might want to keep them in a different place, separated from the domain model to ensure that the domain model doesn't have too many different responsibilities and doesn't need to change very often.
Then, one way can be to implement them as extension methods, because this allows you to keep these business rules separate from your domain model (e.g. User class), but the method is still easily discoverable by users of the User class.
Another way to implement such business rules would be the specification pattern, where you implement each rule as a separate (specification-) class, e.g. demonstrated in this blog post.

There is very little point in using Extension methods for the sake of using them. If the method belongs to the class, use it there. Extension methods are for extending things, use them when you have no control over the class, or for giving functionality to an interface where the functionality should apply to all classes derived from that interface.

if you do not have direct access to the source code for the class you should use Extensions methods if you do have access to the source code i see no reason to not use a standard methods...

I agree with Aaronaught here: Implement your own logic the old-fashioned way. Static method might cause issues (missing using statement and the method seems to be "missing") lateron.
Something inherent to your model should be part of your classes.

Related

How do I define a field ONCE, then use that definition in multiple entities?

I am using class inheritance to add a set of basic fields that all my entities must include. When I do this, EF Core honors any data annotations that exist in the base class, such as [TimeStamp], on the class that is inheriting from it:
public class SomeClass : BaseEntity
{
public string SomeEntityField { get; set; }
}
public class BaseEntity
{
public int Id { get; set; }
public DateTimeOffset UpdatedDate { get; set; }
public DateTimeOffset CreatedDate { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
The above is great when I want to add all inherited fields.
But, what if I wanted to to be able to create a field definition ONCE, and then use that definition in just a few other entities whilst also inheriting from the base class (above) at the same time?
Lets suppose I have this entity, ItemType:
public class ItemType : BaseEntity
{
[StringLength(28)]
public string ItemTypeId { get; set; }
...
I'd like to be able to define the field ItemTypeId in one place, and then use it on multiple entities including the above table WITHOUT having to manually add/maintain the annotation(s) in all those entities. For example, if I need to make the field wider like [StringLength(50)], I adjust it in one place and then all associated fields are updated on the next migration since they all "read" from the same definition. I've tried
using interfaces, but data annotations on interfaces are not honored by EF.
multiple inheritance, but that can't be used because I may need multiple "one-off" fields (and interfaces don't work as per #1)
According to CS1721 nothing will work (ok, with the exception of the single base class itself).
I think ideally I'd like to be able to define the entity fields in CommonFieldType as in the code below, and then have target entities inherit from them, but unfortunately that can't work for the reasons above.
namespace RDCApp.Shared.CommonFieldType
{
public abstract class ItemTypeIdCFT
{
[StringLength(28)]
public string ItemTypeId { get; set; }
}
public abstract class AnotherCFT
{
[StringLength(100)]
public string AnotherField { get; set; }
}
...
I can't be the only person who needs/would like this so is there another way?
I am aware that the Fluent API could be used, but my project is so invested in data annotations that using that (as well as) feels wrong, and means I have 2 places to look in and define field attributes against. Defining against the POCOs directly just feels right to me!
EDIT
To qualify what "feels right to me" means: my VS solution includes both the server (ASP.NET Core) and client side (Blazor WASM) projects. Both tiers can 'see' the entities/POCOs in a shared project and both tiers need to know what the annotations are to perform validation. This means I only need to define validation/attributes once and in turn both tiers have sight of that.
For me, Fluent is not a suitable option - though if this were a typical server side only App I'd shoot for Fluent.
You could define an interface and a generic fluent api helper method to define the fields.
public interface IHasItemType{
int ItemTypeId { get; set; }
}
public void DefineItemType<T> (EntityTypeBuilder<T> builder) where T:IHasItemType{
builder.Property(i => i.ItemTypeId) ...
}
Or you could apply conventions in OnModelCreating
foreach (var table in modelBuilder.Model.GetEntityTypes())
{
foreach (var column in table.GetProperties())
{
// ...
}
}
Fluent API was not suitable for my project need.
Custom annotations would work great for validation logic on both tiers, but unfortunatley DB schema definitions like [StringLength(30)] can't work (or at least I couldn't get to that).
So I landed on a workaround and although I'm not in love with it, it is serviceable for my specific need:
First, I define a particular fields attributes as constants:
public class FieldAttributeValues
{
public const string InventSerialIdComment = "Unique Id of the asset";
public const int InventSerialIdStringLength = 25;
public const bool InventSerialIdRequired = true;
...
}
Then, those constants can be used inside data annotations, for example:
public class SpecAttribute : BaseEntity
{
[Required(AllowEmptyStrings = FieldAttributeValues.InventSerialIdRequired)]
[StringLength(FieldAttributeValues.InventSerialIdStringLength)]
[Comment(FieldAttributeValues.InventSerialIdComment)]
public string InventSerialId { get; set; }
...
}
The downside to this approach is that the developer has to consciously check the FieldAttributeValues class for defined values for a particular field (sort of a manual convention process I guess).
The upshot is that the developer isn't implicity forced to use all of the attributes or even the attribute values as defined, since not all entities will always require the same setup across the patch - i.e. [Required(true)] might generally hold true for most entities, but not some other edge case entity.

Interface Segregation Principle on a collection of objects

I am studying on the SOLID principles and the interface segregation principle is giving me a hard time to understand in a scenario like this one.
Basically, I have a collection of objects... users... that use an interface.
public interface IUserInfo
{
string Name { get; }
string Extension { get; }
}
The issue is that there are some cases where a class that inherits this interface will not use an extension. So to get around that, it simply returns an empty string.
Now, technically this is fine because the string is bound to the UI. So it would simply display an empty string for that field.
However, this violates the Interface Segregation Principle. What is suggested is to split those interfaces.
But then I run into problems where I want this interface in a collection, consider this:
public interface IUserExtension : IUserInfo
{
string Extension { get; }
}
public ObservableCollection<IUserInfo> StoredUserInfos { get; set; } = new ObservableCollection<IUserInfo>()
{
new User1(),
new User2(),
};
public class User1 : IUserExtension
{
public string Name { get; } = "Alex";
public string Extension { get; } = "(715) 925";
public override string ToString()
{
return Name;
}
}
public class User2 : IUserInfo
{
public string Name { get; } = "Daniel";
public override string ToString()
{
return Name;
}
}
I cant bind to the index of this collection and obtain the Extension, because it is an IUserInfo interface. Coincidentally, I also cannot make this a collection of IUserExtension because the User2 class doesn't implement it.
The only way for this to work would be to use pattern matching as far as I am aware
if (UserIndex != -1)
{
var userInfo = StoredUserInfos[UserIndex];
Extension = userInfo is IUserExtension info ? info.Extension : "No Extensions";
Name = userInfo.Name;
}
But that adds a bit of complexity to the code and it may violate other rules because it is checking for the type.
In this case, would the best solution instead would be to implement an abstract class that implements the interface and the default implementation would be an empty string?
This is a difficult one, but I'm going to stick my neck out and attempt to answer.
Does including Extension in the IUserInfo interface violate ISP? I think yes and no.
Let's imagine you want to include a MiddleName property in your IUserInfo interface. A middle name is something that not everyone has but you probably wouldn't want to add that to a separate interface. Along with the Name property, they are a cohesive unit, i.e. they belong together.
In this case, you would probably want to return an empty string (as you have above) or such like. (For more complicated objects with behaviour the Null Object pattern is a much better solution.)
So if we return to your problem above, do you see Extension as something that belongs in an interface on its own? Probably not. Again, let's imagine adding EmailAddress to the IUserInfo interface. Along with Extension, they make a cohesive unit and conceptually represent contact details. If you were to extract these into a separate interface, you would still have some users that do not have an extension in which case you would want to return an empty string (or similar).
So, in answer to your question, I think you could keep Extension in the IUserInfo interface if you are unlikely to extend the interface with any more properties. Otherwise, create an interface that represents the concept of contact details but still returns an empty string if the user doesn't have an extension.

Ensure that all classes will share same method and fields

I my data access layer I want to use DTOs and make sure that all gateways (table data gateway) will implement method which return List of some DTO specific for given gateway.
To make this happen I have created empty interface like this
public interface IDataTransferObject{}
implemented this interface by all DTOs like this
public class UserAccountTypeDTO : IDataTransferObject
{
public int Id { get; set; }
public int AccountTitle { get; set; }
public int CreditTypeId { get; set; }
public bool Active { get; set; }
}
then I have made generic interface for all my gateways
public interface IDefaultGateway<D> where D:IDataTransferObject
{
List<D> Read(SqlDataReader sqlReader);
}
and finally implemented IDefaultGateway by my gateways
class UserAccountTypeGW : IDefaultGateway<UserAccountTypeDTO>
{
private const string Table = " UserAccountType ";
private string SelectAll = "select * from" + Table + "";
private string SelectById = ...;
public List<UserAccountTypeDTO> Read(SqlDataReader sqlReader)
{
throw new NotImplementedException();
}
}
Is it ok to make empty interfaces just to somehow group classes together even if they don't share any behavior?
Fields in gateways are the same only its values are changing. I did copy and paste for fields to each gateway and I would like to know whether there is faster/lazier way how to do this.
Interface and fields are not friends, therefore it could have been defined as properties. Since there is a need to create constructor in each DTO to initialize properties and also make set private it turns out to be little bit worse than what I did.
Abstract class was pretty much the same as interface
Create base class, define fields and methods and initialize (or override) them in gateway constructor is better in this case or pretty much the same as what have I done?
The word you need to search for is called Marker Interfaces. This is the guideline from MSDN:
AVOID using marker interfaces (interfaces with no members).
If you need to mark a class as having a specific characteristic (marker), in general, use a custom attribute rather than an interface.
Having said that, it is easier to check if a class implements an interface than to check if it has an attribute.
And as #Groo has mentioned in the comment section of this answer, which is a really good point:
Marker interfaces also at least give some compile-time checks, compared to attribute
Regarding the second part of the question (how to avoid code duplication), this is what abstract classes are for.
You can provide some default values which derived classes can override if needed:
abstract class BaseGateway<T> : IDefaultGateway<T> where T : IDataTransferObject
{
readonly string _tableName;
readonly string _selectAll;
public BaseGateway()
{
// default table name
_tableName = this.GetType().Name.Replace("DTO", "");
_selectAll = $"select * from {_tableName}";
}
// these members are virtual, so that they can be overriden
protected virtual string TableName => _tableName;
protected virtual string SelectAll => _selectAll;
// derived classes should implement their own 'Read' method
public abstract List<T> Read(IDataReader sqlReader);
}
However, note that doing stuff like this makes your code prone to SQL injection attacks. It would be a better idea to use an ORM, or at least a "micro" ORM like Dapper.
Dapper gives you this simplicity in a couple of plain IDbConnection extension methods:
public class Dog
{
public int Age { get; set; }
public string Name { get; set; }
}
using (IDbConnection conn = OpenConnection())
{
var dog = conn
.Query<Dog>("Select * from Dog where Age = #Age", new { Age = 10 })
.FirstOrDefault();
}
Avoid using those marker interfaces. The only 'good' reason to use marker interfaces nowadays is if you plan to manipulate certain types of objects using reflection (and it's not a case this time).
In this case - abstract class seems to be the best choice. Define that Read() method inside the abstract class and properties with their default implementation. Override it with virtual method in all the descendants as needed. This way you won't even need a wrapper class for reading every specific type of object, as you will be able to reference that object and call Read() on it directly.

Modelling "I'm a * but I'm also a **"

In [this post], I'm struggling to implement a State Pattern as #jonp suggests. I don't quite get how to use what's he's posted but it leads to the thought that maybe I'm trying to fit a square peg into a round hole. So my question:
If I have a visitor to my site that can play multiple roles i.e. a User could be a Vendor, an Employer, an Advertiser, OR all of the above, should I be using inheritance? I've declared:
class Vendor : User {}
class Advertiser : User {}
et cetera, but when a user is both a vendor and an employer then instances of different classes really point to the same underlying object... I'm not sure this can work. How do I model it?
* update *
thanks everyone (you all get a point (it's all I can give)). I've been pulling my hair out over deep-copies with EF, downcasting and the state pattern for the last several days. The role approach makes much more sense.
This sounds like a situation to which the attribute pattern (or so I call it) would be very appropriate. It's a much more loosely-coupled approach than simple inheritance that can be used to specify multiple "behaviours" or in your case kinds of User. It's really nothing more complicated than an object having tags of another kind of object.
The easiest way to implement it would be to have a concrete User class, with a read-only property IList<UserRole> (internally this can be a List<T> field perhaps). Your UserRole class would then be abstract, and VendorRole/AdvertiserRole/etc. would derive from it, allowing you to tag on an arbitrary number of different roles (even ones of the same type) onto a given user. These roles can in addition define their own custom behaviours, utility methods, etc.
In addition, you could define a GetRole<TRole> method on your User class to facilitate access to roles of a specific type (assuming each User only has a single Role of a specific subtype).
Side note: you may also consider the decorator patern, which is closely related to the above mentioned pattern -- though personally I feel it is overkill here, and really adds nothing in terms of flexibility or power. It often just obscures what you're trying to do; though feel free to investigate anyway.
You should favor Composition over Inheritance if the different roles have to contain different logic that would be implemented using polymorphism and abstract methods, for example:
public class User
{
public Role Role { get; set; }
}
public abstract class Role
{
abstract void DoRoleSpecificStuff();
}
public class Vendor : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
public class Employer : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
public class Advertiser : Role
{
public void DoRoleSpecificStuff()
{
/* ... */
}
}
If a User can have multiple Roles, consider using a Roles collection property:
public IEnumerable<Role> Roles { get; set; }
Otherwise, an enumeration using the [Flags] attribute could be fine, too, depending on whether you need to be able to assign multiple Roles:
public class User
{
public Roles Roles { get; set; }
}
[Flags]
public enum Roles
{
Advertiser = 0x0,
Employer = 0x1,
Vendor = 0x2
}
You would assign a combination of different roles as follows:
User user = new User
{
Roles = Roles.Advertiser | Roles.Vendor;
};
That would make the User both an Advertiser and a Vendor, but not an Employer.
“I'm a * but I'm also a **” is known as Multiple Inheritance. C# does not support this, so you shouldn't be considering it.
It's indeed composition over inheritance here, but it's more like this if a single user can have multiple roles.
If there are relatively few roles, a 'parking lot' analogous to an outer join result may work. In this pattern, no Role base class is required.
class User
{
// all of these may be null if not applicable
VendorRole VendorRole { get; set; }
EmployeeRole EmployeeRole { get; set; }
AdvertiserRole AdvertiserRole { get; set; }
}
If a user may have multiple instances of a single role, a collection pops up:
class User
{
// all of these may be null if not applicable
VendorRole VendorRole { get; set; }
EmployeeRole EmployeeRole { get; set; }
ICollection<AdvertiserRole> AdvertiserRoles { get; }
}
Alternatively, if there may be a messy pile of roles, if roles get added dynamically, or what have you, you'll need a collection and a base type. If Entity Framework is involved, though, dynamically added roles seem unlikely to me.
class User
{
ICollection<Role> Roles;
}

"Public" nested classes or not

Suppose I have a class 'Application'. In order to be initialised it takes certain settings in the constructor. Let's also assume that the number of settings is so many that it's compelling to place them in a class of their own.
Compare the following two implementations of this scenario.
Implementation 1:
class Application
{
Application(ApplicationSettings settings)
{
//Do initialisation here
}
}
class ApplicationSettings
{
//Settings related methods and properties here
}
Implementation 2:
class Application
{
Application(Application.Settings settings)
{
//Do initialisation here
}
class Settings
{
//Settings related methods and properties here
}
}
To me, the second approach is very much preferable. It is more readable because it strongly emphasises the relation between the two classes. When I write code to instantiate Application class anywhere, the second approach is going to look prettier.
Now just imagine the Settings class itself in turn had some similarly "related" class and that class in turn did so too. Go only three such levels and the class naming gets out out of hand in the 'non-nested' case. If you nest, however, things still stay elegant.
Despite the above, I've read people saying on StackOverflow that nested classes are justified only if they're not visible to the outside world; that is if they are used only for the internal implementation of the containing class. The commonly cited objection is bloating the size of containing class's source file, but partial classes is the perfect solution for that problem.
My question is, why are we wary of the "publicly exposed" use of nested classes? Are there any other arguments against such use?
I think it's fine. This is basically the builder pattern, and using nested classes works pretty well. It also lets the builder access private members of the outer class, which can be very useful. For instance, you can have a Build method on the builder which calls a private constructor on the outer class which takes an instance of the builder:
public class Outer
{
private Outer(Builder builder)
{
// Copy stuff
}
public class Builder
{
public Outer Build()
{
return new Outer(this);
}
}
}
That ensures that the only way of building an instance of the outer class is via the builder.
I use a pattern very much like this in my C# port of Protocol Buffers.
You can use namespaces to relate things that are... related.
For example:
namespace Diner
{
public class Sandwich
{
public Sandwich(Filling filling) { }
}
public class Filling { }
}
The advantage of this over using classes as if they were namespaces is that you can optionally use using on the calling side to abbreviate things:
using Diner;
...
var sandwich = new Sandwich(new Filling());
If you use the Sandwich class as if it were a namespace for Filling, you have to use the full name Sandwich.Filling to refer to Filling.
And how are you going to sleep at night knowing that?
You might want to check out what Microsoft has to say on the topic. Basically it's a question of style I'd say.
Another practical example that I have for a valid use of public nested classes is in MVC pattern when I use a viewmodel with an IEnumerable property. for example:
public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }
public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}
}
I use it because I don't want Product class to be re-used outside because it is customized only for that specific viewmodel which contains it. But I can't make it private because the Products property is public.
I primarily use nested classes for fine-tuning access to the nested and/or the container class.
One thing to remember is that a nested class definition is basically a class member, and will have access to all the container's private variables.
You can also use this to control usage of a specific class.
Example:
public abstract class Outer
{
protected class Inner
{
}
}
Now, in this case, the user (of your class) can only access the Inner class, if he implements Outer.
I don't know if this is considered bad design or not, but I've got some search classes I make where a user calls the Run() method, passing in an object that holds search criteria. It then returns a collection of search result objects.
These SearchCriteria and SearchResult classes have no utility outside of using them with the Search class. So I nest them under the Search class to show they go together.
I have to make the nested classes public so the client of the Search class can make the SearchCriteria to pass into the Search class and so they can get the results of the Search.
public class PersonSearch
{
public PersonSearchCriteria
{
string FirstName {get; set;}
string LastName {get; set;}
}
public PersonSearchResult
{
string FirstName {get;}
string MiddleName {get;}
string LastName {get;}
string Quest {get;}
string FavoriteColor {get;}
}
public static List<PersonSearchResult> Run(PersonSearchCriteria criteria)
{
// create a query using the given criteria
// run the query
// return the results
}
}
public class PersonSearchTester
{
public void Test()
{
PersonSearch.PersonSearchCriteria criteria = new PersonSearch.PersonSearchCriteria();
criteria.FirstName = "George";
criteria.LastName = "Washington";
List<PersonSearch.PersonSearchResults> results =
PersonSearch.Run(criteria);
}
}

Categories