How to use interface default implementation in C# - c#

I have classes which are inherits from base class.
public class Car : BaseEntity
{
public string Name { get; private set; }
public Car(string name)
{
Name = name;
// update method goes here
}
}
public abstract class BaseEntity
{
public Guid Id { get; } = Guid.NewGuid();
}
I want to have an interface or something else where I can audit this entity changes. I made an interface and added default implementation like below :
public interface IAuditable
{
// userNameProvider goes here
DateTime CreatedTime { get; set; }
Guid CreatedBy { get; set; }
void Audit()
{
CreatedTime = DateTime.UtcNow;
// CreatedBy = userNameProvider.GetUserId();
}
}
But the issue is that I need to cast my Car into this interface in order to call Audit method. As it's not forced to implement in the Car class, I guess I can just forget it or something else. I want a solution which could be reusable for all entities deriving from this interface just by calling one method and not to be afraid to forget Audit method. I'd highly appreciate your suggestions. Thanks
Example code what is working right now but need to simplify :
var car = new Car("bmw");
Console.WriteLine(car.CreatedTime);
public class Car : BaseEntity, IAuditable
{
public string Name { get; private set; }
public DateTime CreatedTime { get; set; }
public Car(string name)
{
Name = name;
(this as IAuditable).Audit();
// update method goes here
}
}
I mentioned above what I did and my expectation, please take a look :)

You can override your DbContext SaveChangesAsync method
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
foreach (var e in ChangeTracker.Entries()
.Where(i => i.State == EntityState.Added
|| i.State == EntityState.Modified)
.Select(i => i.Entity)
.OfType<IAuditable>())
{
e.Audit();
}
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
This will ensure that all IAuditable entities modified through your DB Context will have their Audit method called.

You cannot use default interface methods directly if you don't implement them in the concrete class. However, you can add an extension method to make calling the default interface method easier:
public static class AuditableExtensions
{
public static void Audit(this IAuditable auditable)
{
auditable.Audit();
}
}
// usage:
Car car = new Car();
car.Audit();
// or
public class Car : BaseEntity, IAuditable
{
public Car()
{
this.Audit();
}
}

You can use an external processing class like this:
public class Car : BaseEntity, IAuditable
{
public string Name { get; private set; }
public Car(string name)
{
Name = name;
Auditor.Audit(this);
}
}
public static class Auditor
{
public static void Audit(IAuditable entity)
{
entity.Audit();
}
}

Related

Refactoring classes into multi-layered generic classes in C#

I have a problem with C# generics, and I'm not sure about the most elegant solution. I've been programming a while but am new to the C# ecosystem so don't know common terminology for searching.
I'm trying to refactor code to reduce existing copy-paste duplication of classes. It is easy to resolve with one level of generics, but I can't get it working with two.
A very simplified example is below. The core issue is that BaseProfile cannot use any implementation details relating to DetailsA or DetailsB as it does not know the type. So UpdateDetailsId() has to be duplicated in 2 derived classes, instead of having a single Profile class handle it. Keep in mind this is a toy example just to express the relationships. The real classes have tens of fields, but a common subset which we are using in the class in question, so even if DetailsA and DetailsB look identical assume we need both.
public abstract class BaseProfile<TypeOfPerson>
{
public TypeOfPerson Person { get; set; }
}
public class Profile1 : BaseProfile<PersonA>
{
public void UpdateDetailsId(int id)
{
this.Person.Details.Id = id;
}
}
public class Profile2 : BaseProfile<PersonB>
{
public void UpdateDetailsId(int id)
{
this.Person.Details.Id = id;
}
}
public class PersonA
{
public DetailsA Details { get; set; }
}
public class PersonB
{
public DetailsB Details { get; set; }
}
public class DetailsA
{
public int Id { get; set; }
}
public class DetailsB
{
public int Id { get; set; }
}
I can add interfaces as it is referring to all the same fields for each type. However, C# will not allow an interface to include another interface and automatically resolve it in the implementation, because the member has to exactly match i.e. I thought I could just add IDetails Details to the IPerson interface but the fields now need to be type IDetails instead of DetailsA which implements IDetails. If I do that then I lose compiler type safety and can put the wrong Details on the wrong Person.
I have had success doing a public/private field pair like below, but this only validates and throws at runtime when casting value to DetailsA. I'd prefer something safer but I don't know if this is the best option. The goal of this example is a single Profile class, handling multiple Person classes, each with their own Details type that has an int Id field.
public class PersonA : IPerson
{
public IDetails Details
{
get { return _details; }
set { _details = (DetailsA)value; }
}
private DetailsA _details { get; set; }
}
One way of achieving this is by defining the type relationship between PersonA to DetailsA in a generic way, and specify a second generic type on BaseProfile.
Profile1 : BaseProfile<PersonA, DetailsA>
Consider the following code (note that I'm using Net6, so I have all these nullable reference type operators):
public abstract class BaseProfile<TPerson, TDetails>
where TDetails : IDetails, new()
where TPerson : PersonDetails<TDetails>, new()
{
public TPerson? Person { get; set; } = new TPerson();
public virtual void UpdateDetailsId(int id)
{
Person!.Details!.Id = id;
}
}
public class Profile1 : BaseProfile<PersonA, DetailsA>
{
}
public class Profile2 : BaseProfile<PersonB, DetailsB>
{
}
public abstract class PersonDetails<TDetails>
where TDetails : IDetails, new()
{
public virtual TDetails? Details { get; set; } = new TDetails();
}
public class PersonA : PersonDetails<DetailsA>
{
}
public class PersonB : PersonDetails<DetailsB>
{
}
public interface IDetails
{
int Id { get; set; }
}
public class DetailsA : IDetails
{
public int Id { get; set; }
public string? FirstName { get; set; }
}
public class DetailsB : IDetails
{
public int Id { get; set; }
public string? LastName { get; set; }
}
Testing with the following snippet
var profile1 = new Profile1();
var profile2 = new Profile2();
profile1.UpdateDetailsId(10);
profile2.UpdateDetailsId(12);
Console.WriteLine(profile1.Person!.Details!.Id);
Console.WriteLine(profile2.Person!.Details!.Id);
Console.WriteLine();
Update:
Because you included explicit casting in your snippet for Details property getters and setter, I also want to show a pattern using a concrete type inheriting on these generic types -- then demonstrate implicit/explicit operator user-defined conversion patterns.
Add the following declarations:
public abstract class BaseProfile<TPerson>
where TPerson : PersonDetails<GenericDetails>, new()
{
public TPerson? Person { get; set; } = new TPerson();
public virtual void UpdateDetailsId(int id)
{
Person!.Details!.Id = id;
}
public static explicit operator Profile1(BaseProfile<TPerson> details)
{
var profile = new Profile1();
profile.Person!.Details = (GenericDetails)details.Person!.Details!;
return profile;
}
public static explicit operator Profile2(BaseProfile<TPerson> details)
{
var profile = new Profile2();
profile.Person!.Details = (GenericDetails)details.Person!.Details!;
return profile;
}
}
public class GenericProfile : BaseProfile<GenericPerson>
{
}
public abstract class GenericPersonDetails : PersonDetails<GenericDetails>
{
}
public class GenericPerson : GenericPersonDetails
{
}
public class GenericDetails : IDetails
{
public int Id { get; set; }
public static implicit operator DetailsA(GenericDetails details)
{
return new DetailsA() { Id = details.Id };
}
public static implicit operator DetailsB(GenericDetails details)
{
return new DetailsB() { Id = details.Id };
}
}
and, update the testing functional scope:
var profile1 = new Profile1();
var profile2 = new Profile2();
var genericProfile = new GenericProfile();
profile1.UpdateDetailsId(10);
profile2.UpdateDetailsId(12);
genericProfile.UpdateDetailsId(20);
Console.WriteLine(profile1.Person!.Details!.Id);
Console.WriteLine(profile1.Person!.Details!.FirstName ?? "No First Name");
Console.WriteLine(profile2.Person!.Details!.Id);
Console.WriteLine(profile2.Person!.Details!.LastName ?? "No Last Name");
Console.WriteLine(genericProfile.Person!.Details!.Id);
Console.WriteLine(((Profile1)genericProfile).Person!.Details!.FirstName ?? "No First Name");
Console.WriteLine(((Profile2)genericProfile).Person!.Details!.LastName ?? "No Last Name");
Console.WriteLine();

How can I write a class that is both inheritable and generic?

I have several classes in my project that are mapped to table rows in a database.
Most of the classes share a lot of the boiler plate code to fetch data from database FetchAll, and to return certain object/row based on a given id FetchById().
I am thinking of writing a single class that can perform FetchAll and FetchById() and then all of my other classes can inherit from this object. However, I am struggling to define the base class to be generic. Other classes can't inherit of it and at the same time be of the generic type associated with what they are inheriting from.
To better explain my question, I will start simplifying two of my common classes that share similar code:
Person.cs
class Person {
public int Id { get; set; }
public string Name { get; set; }
public static List<Person> All {
get { /* fetch all rows and */ return List<Person>; }
}
public static Person FetchById(int id) {
return All.Where(p => p.Id == id).SingleOrDefault();
}
}
Department.cs
class Department {
public int Id { get; set; }
public string Name { get; set; }
public string CostCenter { get; set; }
public static List<Department> All { get { /* same logic as with Person */ } }
public static Department FetchById(int id) { /* same logic as with Person */ }
}
Now here is what I tried to do to reduce code duplication:
IIdentifiable.cs
public interface IIdentifiable {
// make sure all objects have an Id property
int Id { get; set; }
}
DbObject.cs
class DbObject<T> where T: IIdentifiable {
public static List<T> All { get { /* return List<T>; */ } }
public static T FetchById(int id) {
return All.Where(object => object.Id == id).FirstOrDefault();
}
}
Now I went back to my Person and Department classes to take advantage of DbObject:
Person.cs (modified)
class Person : DbObject<Person>, IIdentifiable // won't compile: The type cannot be used as type parameter T
{
public int Id { get; set; }
public string Name { get; set; }
// public static List<Person> All {get{ ... }}; // should be inherited
// public static Person FetchById(int id) { ... } // should be inherited
}
I did the same with Department. You get the idea.
I feel I am doing something wrong. I know it should be much simpler than this.
How can I make DbObject generic and inheritable at the same time?
You can do this by adopting the Curiously recurring template pattern.
Effectively you define DbObject<T> such that T : DbObject<T> then it works.
public class DbObject<T> where T : DbObject<T>, IIdentifiable
{
public List<T> All { get { return new List<T>(); } }
public T FetchById(int id)
{
return All.Where(x => x.Id == id).FirstOrDefault();
}
}
public class Person : DbObject<Person>, IIdentifiable
{
public int Id { get; set; }
public string Name { get; set; }
}
Now this code works:
Person p = new Person();
List<Person> all = p.All;
In your original code you were using static methods. I assume that is so you could write List<Person> all = Person.All;, but you can't inherit static methods.
You might want to consider making a repository object that is responsible for returning the people.
Do keep in mind that the downside to this approach is that you need to be careful. This code compiles, but would probably not be what you want:
public class Department : DbObject<Person>, IIdentifiable
{
public int Id { get; set; }
public string Name { get; set; }
}
You can use recursive generics and static methods.
public abstract class Identified<T> where T : Identified<T>{
public static List<T> GetAll(){...}
}
public class Person:Identified<Person>{...}
var allPeople = Person.GetAll();
You shouldn't need to redefine GetAll in each subtype. But I would recommend that FetchById performs a separate query. Do you really want to load the entire table to view one record?
But I would actually recommend a separate generic factory class. It's difficult to configure and test static methods.

Passing any model class to a common method C#

So, I want to create an interface which has a method that can take in any model class.
For example
I have these three property class
class A
{
public long id { get; set; }
public string description { get; set; }
public string code { get; set; }
}
class B
{
public long someID { get; set; }
}
class C
{
public long anydesign { get; set; }
}
class D
{
public long Router { get; set; }
}
I have an interface
public interface IModel
{
void Dosomething(A model); // Now in this example it takes the A model,But I want it to be set, so that that class that implements the interface can put any model as required
}
Now, I have a class that implements the mode
Since the interface only takes the A model, I can pass in the A model in the class during implementation
public class ImplemenationA: IModel
{
public void Dosomething(A model)
{
Console.WriteLine(model.description);
}
}
Say i have another implemenation Class
Now, I am guessing the below one wouldnt work, as the interface signature enforces only to take a Model A and not any other model
public class ImplementationB:IModel
{
public void Dosomething(B model)
{
Console.WriteLine(model.someID);
}
}
I want to the interface method to be invoked by any implementation class and use any model
While it is unjustified what you're attempting to do... to answer the actual question it is possible using generics...
Take the following for guidance (and example)...
class Test : IJobTask
{
public void Start(string val = "")
{
throw new NotImplementedException();
}
}
public interface ITest
{
void MyMethod<T>(T model) where T : IJobTask;
}
public class ConcreteTest : ITest
{
public void MyMethod<T>(T model) where T : IJobTask
{
}
}
public class Main
{
public Main()
{
var ct = new ConcreteTest();
ct.MyMethod(new Test());
}
}
Your MyMethod will need to perform checks and casts now which kind of defeats the purpose, but this does answer the question of "a method accepting any model"
Use interface for your property classes.
public interface IProperty
{
...
}
class A: IProperty
{
...
}
class B: IProperty
{
...
}
class C: IProperty
{
...
}
class D: IProperty
{
...
}
And then you can pass interface as a parameter:
public interface IModel
{
int getModel(IProperty model);
}

Struggling with the C# generics, is this possible?

I'm currently on design stage in writing C# .NET Core application. I'm gonna use the generics to inherit some properties among all derived classes. The goal is to archive many 2 many relation of entities able to be tagged. The app concept is funky, because tag will contain related logic as constraint entity. I have problems with the proper where statements in generic class, to be able to use inherited Tags property for all Taggable Entities.
Here is abstraction:
public interface ITaggable
{
long TagId { get; set; }
Tag Tag { get; set; }
}
public interface IEntityTag<T> : ITaggable where T : Entity
{
long EntityId { get; set; }
T Entity { get; set; }
}
public abstract class TaggableEntity<T> : Entity where T : ITaggable
{
public ICollection<T> EntityTags { get; set; }
public List<Tag> Tags { get { return EntityTags.Select(x => x.Tag).ToList(); } }
}
public abstract class ConstraintBase<TSubject, TOwner>
: ConstraintEntity where TOwner : TaggableEntity<IEntityTag<TOwner>>
{
protected ConstraintBase(ConstraintId id, string description)
{
Id = id.Value();
Name = id.ToString();
Description = description;
IsExecutable = false;
}
public IEnumerable<TSubject> Validate(IEnumerable<TSubject> items, TOwner owner)
{
return items.Where(x => Validate(x, owner));
}
public void Execute()
{
if (IsExecutable) { OnExecuting(); }
}
protected abstract bool Validate(TSubject item, TOwner owner);
public abstract void OnExecuting();
}
And here concrete classes.
public class ConstraintEntity : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsExecutable { get; set; }
public ConstraintId ConstraintId => (ConstraintId)Id;
}
public class EndWorkConstraint : ConstraintBase<Activity, User>
{
public EndWorkConstraint() : base(ConstraintId.EndWorkConstraint, "Check if user is allowed to end work")
{
}
protected override bool Validate(Activity item, User owner)
{
return item.ActivityId != ActivityId.EndWork;
}
public override void OnExecuting()
{
throw new System.NotImplementedException();
}
}
public class User : TaggableEntity<UserTag>
{
public string Login { get; set; }
public string Password { get; set; }
}
The question is: am I able to modify ConstraintBase where statement, to make EndWorkConstraint class do not raising an error, and still have the tags explicit avalible?
This is my first post on the forum, and I m really forced to use Yours wisdom. I'd be glad for any tips. Thanks in advance.

How to access the derived class properties from base class instance using generic method

I am trying to access all the properties of my derived class through base class reference variable.
Classes
public class vehicle
{
public int ID { get; set; }
}
public class Car : vehicle
{
public string type { get; set; }
public string Name { get; set; }
}
Here is the main in Main class
public static void saveCar<T>(T vehicle) where T : vehicle
{
//TODO : here I need to access all the propertie values but I dunno how access only derived class values
}
I am trying to do this way
static void Main(string[] args)
{
Car cr = new Car
{
ID = 1,
type = "car",
Name = "Maruthi"
};
saveCar<Car>(cr);
}
You can't really ask for T and know your real properties.
I think you should change your design to something like this:
public abstract class Vehicle
{
public int Id { get; set; }
public virtual void SaveCar()
{
// save Id
}
}
public class Car : Vehicle
{
public string Type { get; set; }
public string Name { get; set; }
public override void SaveCar()
{
base.SaveCar();
// Save type & name
}
}
Why do you have saveCar as a generic method? If the saveCar method is a virtual method on Vehicle you can override and have the required extended save functionality in each derived type.
However if you require an external method to handle actions such as save and have Vehicle and its derived classes as simple data representations, you will need to inspect the object and act accordingly. Some like:
public static void saveCar(Vehicle vehicle)
{
if (vehicle != null)
{
Console.WriteLine(vehicle.ID);
if (vehicle is Car)
{
var car = vehicle as Car;
Console.WriteLine(car.Name);
}
}
}

Categories