Reputation: 261
I have created a dot net fiddle that shows the requirement in action.
Basically I have a lot of business classes that inherit from a base class. And I want to be able to dynamically add logic to all of them to be executed after they create entities.
In this specific case, I want to able to log entities that are created.
This is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
var businessClasses = typeof(IEntity)
.Assembly
.GetTypes()
.ToList()
.Where(i => i.BaseType != null)
.Where(i => i.BaseType.Name.StartsWith("Business"))
.ToList();
Console.WriteLine(businessClasses.Count);
foreach (var businessClass in businessClasses)
{
var postCreationAugmenters = businessClass.GetField("PostCreationAugmenters", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static).GetValue(null);
// how can I add the LogAugmenter.LogCreation to the postCreationAugmenters list?
}
public static class LogAugmenter
{
public static void LogCreation(IEntity entity)
{
}
}
public interface IEntity
{
long Id { get; set; }
}
public class Blog : IEntity
{
public long Id { get; set; }
}
public class Business<T>
where T : IEntity
{
public static List<Action<T>> PostCreationAugmenters = new List<Action<T>>();
public T Create(T entity)
{
// Inserting the model inside the database and returning it with the assigned Id
foreach (var augmenter in PostCreationAugmenters)
{
augmenter.Invoke(entity);
}
return entity;
}
}
public class BlogBusiness : Business<Blog>
{
}
How can I add the LogAugmenter.LogCreation
to the postCreationAugmenters
list that is extracted via reflection.
Upvotes: 0
Views: 193
Reputation: 4218
You have to take the following steps to add your method to the generic list:
List.Add
method.List.Add
and pass the create delegate.Have a look at this example, but as mentioned in the comments, i think you gain nothing by choosing this design. Going with a typesafe approach using interfaces will save you from a lot of hard to maintain and debug reflection calls.
foreach (var businessClass in businessClasses)
{
var postCreationAugmenters = businessClass.GetField("PostCreationAugmenters", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static).GetValue(null);
// how can I add the LogAugmenter.LogCreation to the postCreationAugmenters list?
var targetMethod = typeof(LogAugmenter).GetMethod(nameof(LogAugmenter.LogCreation));
var targetMethodDelegate = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(businessClass.BaseType.GetGenericArguments()), targetMethod);
var listAddMethod = postCreationAugmenters.GetType().GetMethod("Add");
listAddMethod.Invoke(postCreationAugmenters, new object[] { targetMethodDelegate });
}
Upvotes: 3