I want to do this for all my Types Of AuditedEntity, but as we've told FH to ignore base abstracts, the code isnt getting hit. i dont want to do this for all my entities and then have someone forget when they add a new typeof<AuditedEntity>
public abstract class AuditedEntity : Entity ...
public class AuditedEntityMappings : IAutoMappingOverride<AuditedEntity>
{
public void Override(AutoMapping<AuditedEntity> mapping)
{
mapping.Where("DeletedById is null");
}
}
This post looked promising but that method is deprecated
Got it working thanks to some help on some reasonably complex expressions leading to the following extensions:
var model =
AutoMap.AssemblyOf<AuditedEntity>(new AutomappingConfiguration(databaseName))
.HideDeletedEntities();
...
public static class ReflectiveEnumerator
{
public static IEnumerable<Type> GetSubTypesOf<T>() where T : class
{
return Assembly.GetAssembly(typeof (T)).GetTypes()
.Where(myType => myType.IsClass &&
!myType.IsAbstract &&
myType.IsSubclassOf(typeof (T)));
}
}
public static class AutoPersistenceModelExtensions
{
public static AutoPersistenceModel HideDeletedEntities(this AutoPersistenceModel model)
{
var types = ReflectiveEnumerator.GetSubTypesOf<AuditedEntity>();
foreach (var t in types)
{
var mapped = typeof(AutoMapping<>).MakeGenericType(t);
var p = Expression.Parameter(mapped, "m");
var expression = Expression.Lambda(Expression.GetActionType(mapped),
Expression.Call(p, mapped.GetMethod("Where"),
Expression.Constant("DeletedById is null")), p);
typeof(AutoPersistenceModel).GetMethod("Override").MakeGenericMethod(t)
.Invoke(model, new object[] { expression.Compile() });
}
return model;
}
}
Related
How do I make this expression dynamic based on the generic type passed in the parameter?
In the simplified form:
public static class CompareService
{
public static List<T> Run<T>(List<T> database_list, string directory_path)
{
var csv_list = CompareService.MergeRecordsFromFiles<T>(directory);
return CompareService.RunComparison<T>(database_list, csv_list);
}
public static T CompareData<T>(List<T> database_list, List<T> csv_list)
{
var diff = new List<T>();
foreach (var db_item in database_list)
{
// ...
// if T is of type Deathstar compare reference_number property
// if T is of type Stormtrooper compare id property
// if T is of type Sith compare id and anger_level property
var csv_item = csv_list.FirstOrDefault(x => x.reference_number == db_item.reference_number);
// Comparison code
ComparisonResult result = compareLogic.Compare(db_item, csv_item);
// ...
}
return diff;
}
}
It is called from another generic service:
public static void Whatever<T>(List<T> list)
{
// ...
var directory_path = "C:\";
var delta = CompareService.CompareData<T>(list, directory_path);
// ...
}
The most naive implementation would be to check if your itemToFind can be cast to DeathStar, StormTrooper or Sith and if so call the instances property.
var deathStar = itemToFind as DeathStar;
if(deathStar != null)
return database_list.Where(x => ((DeathStar)x).reference_number == deathStar.reference_number).FirstOrDefault();
else
{
var sith = itemToFind as Sith;
if(sith != null)
return database_list.Where(x => ((Sith)x).anger_level == sith.anger_level).FirstOrDefault();
else
return database_list.Where(x => ((StormTrooper)x).id== ((StormTrooper)item).id).FirstOrDefault();
}
This is quite cumbersome, including many casts. In particular it completely bypasses the actual benefits of generics using any arbitrary type (that fullfills the constraints if existing). In your case you´d have a generic method that will only wortk for three decent types.
A better approach is to let all your classes implement a common interface that defines a property, for instance:
interface IObject {
int Level { get; }
}
Now all classes define that level-property:
clas DeathStar : IObject
{
public int Level { get { return this.reference_number; } }
}
clas Sith : IObject
{
public int Level { get { return this.anger_level; } }
}
clas StormTrooper: IObject
{
public int Level { get { return this.id; } }
}
Than you can use a constraint on your type T to implement that interface:
public static T CompareData<T>(List<T> list, T itemToFind) where T: IObject
Why not like this:
public static T CompareData<T>(List<T> list, Func<T, bool> predicate)
{
return database_list.FirstOrDefault(predicate);
}
And then use it like this:
var itemToFind = new ItemToFind();
var myObjectList = new List<MyObject>();
var item = CompareData<MyObject>(myObjectList, x=> x.MyObjectProperty == itemToFind.Id);
You could add a property selector:
public static class CompareService
{
public static T CompareData<T>(this List<T> list, T itemToFind, Func<T, int> propSelector)
{
int propToFind = propSelector(itemToFind); // cache
return database_list.FirstOrDefault(x => propSelector(x) == propToFind);
}
}
And call it like that:
listOfDeathstars.CompareData(deathStarToFind, ds => ds.reference_number);
listOfStormtroopers.CompareData(trooperToFind, t => t.id);
listOfSiths.CompareData(sithStarToFind, sith => new { sith.id, sith.anger_level});
Note: I added the this keyword in the signature to make it an extension (not sure if you intended that but forgot the keyword). And Where(predicate).FirstOrDefault() can be reduced to FirstOrDefault(predicate).
Ive got what I think may be an unusual problem (Ive searched around a lot for an answer, but I dont think Ive found one).
I have messages that are read from a queue and depending on the message type contains a payload that needs to be deserialized into a concrete c# class. This needs to eventually be concrete (I cant use generics the whole way) because Im using Expression Trees to perform Evaluations on the classes that arrive from the queue.
The base class looks like this:
public abstract class BaseRuleMessage<T>
{
public abstract Func<T, bool> CompileRule(Rule r, T msg);
public T Deserialize(ClientEventQueueMessage message)
{
return JsonConvert.DeserializeObject<T>(message.Payload);
}
public BaseRuleMessage()
{
RulesCompleted = new List<int>();
}
public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
{
return ruleGroup.Rules.Where(item =>
!RulesCompleted.Any(r => r.Equals(item.Id)));
}
I implement the base class like this:
public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{
public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
{
var expression = Expression.Parameter(typeof(UiTransactionUpdate));
Expression expr = BuildExpr(r, expression, msg);
return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
}
public Guid TransactionId { get; set; }
public Guid GroupId { get; set; }
public decimal StatusValue { get; set; }
I then do something like this to call:
switch (message.MessageType)
{
case "UI_UPDATE":
{
message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
var deserializedMessage = new UiTransactionUpdate().Deserialize(message);
deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();
foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
{
What I really want to know is how can I create a factory (or can I?) to be able to define the implementation of the base class in such a way that I can return a concrete class to use for my expression tree evaluations without having to repeat all the calling code for each type.
I avoided using dynamic but this meant that I had pass the object around as an object. I prefer not to use dynamic but in this case, casting objects at run-time may not be any better.
I also had to change the code so that instead of returning a Func<T, bool>, there is a method that would execute the Func. This was to avoid referring to the generic class. I'm not sure if you actually need the Func in your actual implementation.
I had to create a new base class that wasn't generically typed.
// Horrible name, do change it to something more appropriate
public abstract class BaseBaseRuleMessage
{
public IList<int> RulesCompleted { get; set; }
public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
{
return ruleGroup.Rules.Where(item =>
!RulesCompleted.Any(r => r.Equals(item.Id)));
}
public BaseBaseRuleMessage DeserializeToBaseBaseRuleMessage(ClientEventQueueMessage message)
{
return (BaseBaseRuleMessage) DeserializeToType(message);
}
protected abstract object DeserializeToType(ClientEventQueueMessage message);
public abstract bool ExecuteRule(Rule rule, object msg);
}
Updated the BaseRuleMessage to derive from BaseBaseRuleMessage (and moved some properties to the base class.
public abstract class BaseRuleMessage<T> : BaseBaseRuleMessage
where T : BaseRuleMessage<T>
{
public abstract Func<T, bool> CompileRule(Rule r, T msg);
protected override object DeserializeToType(ClientEventQueueMessage message)
{
return JsonConvert.DeserializeObject(message.Payload, typeof(T));
}
protected BaseRuleMessage()
{
RulesCompleted = new List<int>();
}
public override bool ExecuteRule(Rule rule, object msg)
{
var message = (T) msg;
if (message == null)
{
throw new InvalidOperationException();
}
return CompileRule(rule, message).Invoke(message);
}
}
The concrete class is basically the same. I've implemented my own BuildExpr to make sure the code can compile.
public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{
public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
{
var expression = Expression.Parameter(typeof(UiTransactionUpdate));
Expression expr = BuildExpr(r, expression, msg);
return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
}
public Guid TransactionId { get; set; }
public Guid GroupId { get; set; }
public decimal StatusValue { get; set; }
private Expression BuildExpr(Rule rule, ParameterExpression parameterExpression, UiTransactionUpdate message)
{
var transactionIdProperty = Expression.Property(parameterExpression, "TransactionId");
var value = Expression.Constant(rule.TransactionId);
return Expression.Equal(transactionIdProperty, value);
}
}
To use it:
var messageTypeToTypeMap = new Dictionary<string, Func<BaseBaseRuleMessage>>
{
{"UI_UPDATE", () => new UiTransactionUpdate()}
};
var factoryFunc = messageTypeToTypeMap[message.MessageType];
message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
var ruleMessage = factoryFunc.Invoke();
var deserializedMessage = ruleMessage.DeserializeToBaseBaseRuleMessage(message);
deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();
foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
{
var isTrue = deserializedMessage.ExecuteRule(rule, deserializedMessage);
}
I'm overriding the ValidateEntity method to check for unique validation and I've hit a stumbling block.
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var result = new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
if (entityEntry.Entity is ReferenceType && entityEntry.State == EntityState.Added)
{
var entity = entityEntry.Entity as ReferenceType;
var pluralService = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-gb"));
var pluralEntity = pluralService.Pluralize(entity.GetType().Name);
// I would like Courses to be replaced with the property name of pluralEntity
if (Courses.Where(x => x.Title == entity.Title).Count() > 0)
{
result.ValidationErrors.Add(new DbValidationError(nameof(entity.Title), nameof(entity.Title) + " must be unique."));
}
}
if (result.ValidationErrors.Count > 0)
{
return result;
}
else
{
return base.ValidateEntity(entityEntry, items);
}
}
In my SchoolContext class I have the property DbSet<Course> Courses which is a ReferenceType (a custom abstract class type).
The value of pluralEntity is Courses, but I want to put in the if-statement something similar to:
if (Property(pluralEntity).Where(x => x.Title == entity.Title).Count() > 0)
{
// validate
}
Is there a way to do this?
Update
I've got this:
var prop = (DbSet<ReferenceType>) GetType().GetProperty(pluralEntity).GetValue(this, null);
if (prop.Where(x => x.Title == entity.Title).Count() > 0)
{
result.ValidationErrors.Add(new DbValidationError(nameof(entity.Title), nameof(entity.Title) + " must be unique."));
}
But because ReferenceType is an abstract class it cannot cast it at runtime.
I'd like to do something like this
var prop = (DbSet<typeof(entityEntry.Entity.GetType().Name)>)
But of course that's a variable and can't be passed in as a generic type
The only thing I can think of at the moment is writing a custom validation method, using the repository pattern.
First, create an interface which all your entities will implement
public interface IEntity
{
public string Title {get; set; }
}
Then create the repository:
public class Repository<TEntity> where TEntity: class, IEntity
{
private YourContext context = new YourContext();
private DbSet<TEntity> AppDbSet;
public Repository()
{
AppDbSet = context.Set<TEntity>();
}
//a couple of method to retrieve data...
public List<TEntity> GetAll()
{
return AppDbSet.ToList();
}
public IEnumerable<TEntity> Find(Func<TEntity, bool> predicate)
{
return AppDbSet.Where<TEntity>(predicate);
}
public TEntity Single(Func<TEntity, bool> predicate)
{
return AppDbSet.FirstOrDefault(predicate);
}
//Lastly, implement a validation method
public bool IsValid(TEntity entity)
{
if (AppDbSet.SingleOrDefault(x => x.Title == entity.Title) != null)
return false;
else
return true;
}
}
Use the repository as follow:
Repository<Course> courseRepository = new Repository<Course>();
Course course = new Course();
course.Title = "Boring course";
Console.WriteLine(courseRepository.IsValid(course));
Hope it helps.
I have a extension method that checks the object for its type and then populate its member property
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository)
where T: MyEntity
{
var agenda = entity as Agenda;
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
}
var participant = entity as Participant;
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
}
}
can I further refactor that to something like this to make it more generic?
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T : MyEntity
{
var obj = entity as Agenda || entity as Participant;
if (obj != null)
{
obj.Meeting = meetingRepository.GetMeetingById(obj.MeetingId);
}
}
}
PS: I don't want to put the object's property Meeting in the Base class (MyEntity)
I would, personally, just use overloads:
public static void LoadMeeting(this Agenda agenda, IMeetingRepository meetingRepository)
{
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
}
}
public static void LoadMeeting(this Participant participant, IMeetingRepository meetingRepository)
{
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
}
}
You couldn't do it with a single generic method unless you had some shared contract (either a base class or interface implemented) which provided the Meeting property.
The alternative would be to make a shared interface, ie: IMeeting, then constrain to that:
public interface IMeeting
{
public Meeting Meeting { get; set; }
public int MeetingId { get; }
}
Then you can write:
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository)
where T: IMeeting
{
if (entity != null)
{
entity.Meeting = meetingRepository.GetMeetingById(entity.MeetingId);
}
}
As you're using EF, you could implement this interface in a partial class:
public partial class Agenda : MyEntity, IMeeting
{
}
You may want to return early out of the method incase you have to handle a class and it's base class.
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity
{
var agenda = entity as Agenda;
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
return;
}
var participant = entity as Participant;
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
return;
}
}
You might also consider a table approach:
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity {
var name = entity.GetType().Name;
if (Table.ContainsKey(name)) {
Table[name](entity, meetingRepository);
}
}
Where Table is:
static Dictionary<String, Action<MyEntity, IMeetingRepository>> Table = new Dictionary<String, Action<MyEntity, IMeetingRepository>>();
And it is initialized like so:
Table.Add("Agenda", (agenda, meetingRepository) => {
((Agenda)agenda).Meeting = meetingRepository.GetMeetingById(((Agenda)agenda).MeetingId); });
Table.Add("Participant", (participant, meetingRepository) => {
((Participant)participant).Meeting = meetingRepository.GetMeetingById(((Participant)participant).MeetingId); });
Obviously your Table will have to be static and available to your extension method (say in the containing class).
I wrote a class that allows a derivate to specify which of its properties can be lazy loaded. The code is:
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
And a derivate class:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address", () => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
This works perfectly fine for getting and settings property values, but I get a either a RuntimeBinderException when I implicitly cast or an InvalidCastException with an explicitly cast SelfHydratingEntity back to T.
I know that you can override the DynamicObject.TryConvert method, but I'm wondering what exactly to put in this method. I've read a lot about duck typing today, and have tried out several libraries, but none of them work for this particular scenario. All of the libraries I've tried today generate a wrapper class using Reflection.Emit that makes calls to "get_" and "set_" methods and naturally use reflection to find these methods on the wrapped instance. SelfHydratingEntity of course doesn't have the "get_" and "set_" methods defined.
So, I'm wondering if this kind of thing is even possible. Is there any way to cast an instance of SelfHydratingEntity to T? I'm looking for something like this:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
Have you seen this Duck Typing project. It looks pretty good. I have just found a great example from Mauricio. It uses the Windsor Castle dynamic proxy to intercept method calls
Using the code from Mauricio the following code works like a dream
class Program
{
static void Main(string[] args)
{
dynamic person = new { Name = "Peter" };
var p = DuckType.As<IPerson>(person);
Console.WriteLine(p.Name);
}
}
public interface IPerson
{
string Name { get; set; }
}
public static class DuckType
{
private static readonly ProxyGenerator generator = new ProxyGenerator();
public static T As<T>(object o)
{
return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
}
}
public class DuckTypingInterceptor : IInterceptor
{
private readonly object target;
public DuckTypingInterceptor(object target)
{
this.target = target;
}
public void Intercept(IInvocation invocation)
{
var methods = target.GetType().GetMethods()
.Where(m => m.Name == invocation.Method.Name)
.Where(m => m.GetParameters().Length == invocation.Arguments.Length)
.ToList();
if (methods.Count > 1)
throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
if (methods.Count == 0)
throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
var method = methods[0];
if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
method = method.MakeGenericMethod(invocation.GenericArguments);
invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
}
}
impromptu-interface
https://github.com/ekonbenefits/impromptu-interface
Can static cast interfaces onto objects derived from DynamicObject.