Update a specific column of a List <T> - c#

First they forgive me for my English since it is not my native language.
I have a method which receives a generic list List<T>. what I want is to foreach through the whole list and be able to update a column called Eliminated of each class T and which is of the boolean type, is it possible to do? can anybody help me.
This is what I have so far:
// Delete (Change status delete = true)
public void Delete<T>(List<T> data)
{
if (data != null)
{
data.ForEach(x =>
{
...
});
}
}
Thanks in advance!

Instead of T i would use an interface, because otherwise in the foreach you cannot access the property Eliminated.
Here the interface:
interface IExample {
bool IsEliminated { get; set; }
}
and here the method with the ForEach loop.
public void Delete<T>(List<T> data) where T : IExample
{
if (data != null)
{
data.ForEach(x =>
{
x.Eliminated = true;
});
}
}

If you want a generic method to update a list of any type, you could do something like this:
public void Update<T>(List<T> data, Action<T> func)
{
if (data == null)
throw new ArgumentNullException(nameof(data));
data.ForEach(func);
}
Note I've change the null check to throw if you pass in a null list. You could just return here instead, this way eliminates some nesting.
This allows you to pass in an action that you apply to every item in a collection. You would use it like this:
var data = new List<YourClass> = GetData();
Update(data, item => item.Eliminated = true);

Your T has no property called Eliminated. Your compiler cannot guarantee that any T you will ever use with this method will have that member, so you are not allowed to compile it that way.
You could put a constraint on your T that allows the compiler to make sure the property exists:
public interface Eliminatable
{
bool Eliminated { get; set; }
}
public void Delete<T>(List<T> data) where T : Eliminatable
{
if (data != null)
{
data.ForEach(x => { x.Eliminated = true; });
}
}
Or (and some may say this is a hack) you can just trust your users that they will in fact pass something as T that confirms to your pattern:
public void Delete<T>(List<T> data)
{
if (data != null)
{
data.ForEach(x => { dynamic d = x; d.Eliminated = true; });
}
}
Now this will fail if the property is not there. At runtime. Not nice. But it "works".

Related

audit trail with entity framework

I have fields for audit trail in each table (InsertedBy, InsertedDate, UpdatedBy and UpdatedDate), I build solution to reduce redundant before by override savechange():
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries().Where(e =>
e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified))
{
Auditing.ApplyAudit(entry, User);
}
return base.SaveChanges();
}
public class Auditing
{
public static void ApplyAudit(DbEntityEntry entityEntry, int User)
{
Type type = entityEntry.Entity.GetType();
if (entityEntry.State.ToString() == "Added")
{
if (type.GetProperty("InsertedBy") != null)
{
entityEntry.Property("InsertedBy").CurrentValue = User;
}
if (type.GetProperty("InsertedDate") != null)
{
entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
}
}
else if (entityEntry.State.ToString() == "Modified")
{
if (type.GetProperty("InsertedBy") != null)
{
entityEntry.Property("InsertedBy").IsModified = false;
}
if (type.GetProperty("InsertedDate") != null)
{
entityEntry.Property("InsertedDate").IsModified = false;
}
if (type.GetProperty("UpdatedBy") != null)
{
entityEntry.Property("UpdatedBy").CurrentValue = User;
}
if (type.GetProperty("UpdatedDate") != null)
{
entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
}
}
}
}
the question is:
is using reflection within each entity before modified or added waste in memory and performance ? if yes is there is best practice for this ?
is this another code snippet better in performance or just use reflection also?
public static void ApplyAudit(DbEntityEntry entityEntry, long User)
{
if (entityEntry.State.ToString() == "Added")
{
entityEntry.Property("InsertedBy").CurrentValue = User;
entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
}
else if (entityEntry.State.ToString() == "Modified")
{
entityEntry.Property("InsertedBy").IsModified = false;
entityEntry.Property("InsertedDate").IsModified = false;
entityEntry.Property("UpdatedBy").CurrentValue = User;
entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
}
}
is entityEntry.Property("InsertedBy") uses reflection ?
Reflection is slow (slow is subjective) and if you want to avoid it, then you need to get rid of such code as below:
Type type = entityEntry.Entity.GetType();
if (type.GetProperty("InsertedBy") != null)
Even if it was not slow, the code above is still "buggy" because a programmer may mistakenly write InsertBy instead of InsertedBy. This can easily be avoided with help from the compiler using the approach below.
Use an interface and implement it in all entities that require audit.
public interface IAuditable
{
string InsertedBy { get; set; }
// ... other properties
}
public class SomeEntity : IAuditable
{
public string InsertedBy { get; set; }
}
public class Auditor<TAuditable> where TAuditable : IAuditable
{
public void ApplyAudit(TAuditable entity, int userId)
{
// No reflection and you get compiler support
if (entity.InsertedBy == null)
{
// whatever
}
else
{
// whatever
}
}
}
As mentioned in the comments, you will get compiler support and reflection is not used anymore. I would even go a step further and not pass the int userId. I will bring the code for figuring out the userId and put it in this class. That way the class is self sufficient and clients do not need to provide it this information.
Usage:
var e = new SomeEntity();
var auditor = new Auditor<SomeEntity>();
auditor.ApplyAudit(e, 1); // 1 is userId, I am just hardcoding for brevity
Or use it from your context:
public override int SaveChanges()
{
var auditables = ChangeTracker.Entries().Where(e =>
e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified)
.OfType<IAuditable>();
var auditor = new Auditor<IAuditable>();
foreach (var entry in auditables)
{
// 1 is userId, I am just hardcoding for brevity
auditor.ApplyAudit(entry, 1);
}
return base.SaveChanges();
}
This means that all entities who are auditable will need to implement the IAuditable interface. EF generates partial classes for your entities but do not modify those partial classes because the next time you run the custom tool, it will be wiped out.
Instead, create another partial class with the same name and implement the IAuditable.
public partial class SomeEntity : IAuditable {}
An even better approach is to create a custom T4 template so it creates the partial class with the code : IAuditable. Please see this article for how to do that.

Passing class type to generic method at runtime

I have an interface called IAuditable as follows:
public interface IAuditable
{
string AuditSummary
{
get;
}
string AuditDetails
{
get;
}
}
And two generic method in AuditTrail class as follows:
public T GetActualOldValue<T>() where T : IAuditable
{
return FromXElement<T>(OldValue);
}
public T GetActualNewValue<T>() where T : IAuditable
{
return FromXElement<T>(NewValue);
}
as well as i have one property to returning Audit Summary by getting a class at run time as follows:
public string AuditSummary
{
get
{
if (HasNewValue || HasOldValue)
{
string libraryVal = GetLibraryValue();
Assembly assembly = Assembly.Load(libraryVal);
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass == true)
{
if (type.FullName.EndsWith("." + ClassName))
{
/*Here i want to call GetActualNewValue<foundClass>().AuditSummary
* or GetActualOldValue<foundClass>().AuditSummary;
*/
}
}
}
}
return "";
}
}
As you know we can find class at run time in specific library,
Please note i don't want to call a generic method at run time,just wanna call generic method with founded, in other words how can i pass a specific class to GetActualNewValue<...>() as T,
AuditTrail auditTrail = AuditTrail.GetAuditTrail(76);
string summmary = auditTrail.GetActualOldValue<DTClient>().AuditSummary;
string details = auditTrail.GetActualOldValue<DTClient>().AuditDetails;
This code work perfectly but the main problem is DTClient must find at run time and define as T for GetActualValue.
Thanks all.
Try this:
AuditTrail auditTrail = new AuditTrail();
var method = auditTrail.GetType().GetMethod("GetActualOldValue");
var genericMethod = method.MakeGenericMethod(auditTrail.GetType());
var result = genericMethod.Invoke(auditTrail, null);
You can use static method passing old object and changed object in parameters to track changes.
public class
{
AuditClass.AuditingUserActivity(OldObject,ChangedObject);
}
class AuditClass
{
public static void AuditingUserActivity<T>(this T obj1,obj2)
{
PropertyInfo[] properties = typeof(T).GetProperties(); //Gets all properties exist in passed objects of both
foreach (PropertyInfo pi in properties)
{
object value1 = typeof(T).GetProperty(pi.Name).GetValue(obj1, null); // gets value for each entity
object value2 = typeof(T).GetProperty(pi.Name).GetValue(obj2, null);
if (value1 != null && value2 != null)
{
//You can compare and check whether changes made or not
}
}
}
}

Strange control flow

I'm working on a framework in C# that will depend on pluggable components implemented as classes inheriting a base class. In order to make the components as simple as possible, I am working on some weird control flow.
The base class includes a static method RunStep(parameter). This method is called a number of times by the inheriting class, and each time it is called a condition is checked. If this condition happens to be false, I want the calling method to stop and return. A simplified working version of the code would be:
Base class:
class MyBase
{
private static object RunStep(string parameter)
{
if(SomeFunction(parameter))
return SomeOtherFunction(parameter);
else
return null;
}
}
Inheriting class:
class MyInheritor
{
public void Run()
{
object result = RunStep("mystring1");
if(null != result)
{
//perform some logic on result
result = RunStep("mystring2");
if(null != result){
//perform some different logic on result
RunStep("mystring3");
}
}
}
}
What I am wondering is whether it is possible to do something in the base class so that I can simplify the inheriting class to this:
class MyInheritor2
{
public void Run()
{
object result = RunStep("mystring1");
//perform some logic on result
result = RunStep("mystring2");
//perform some different logic on result
result = RunStep("mystring3");
}
}
}
I would put the parameters in a list and loop over them, but there is logic that needs to happen after each call to the RunStep method, and the logic is different each time. This takes a loop off the table. Also note that the logic between the RunStep calls accesses properties on result, so it crashes without the null checks.
It may seem like a trivial thing, but there may be thousands of these Inheriting classes and simplifying them is a big deal.
Let the base class to control the execution flow:
class Base
{
private readonly List<Tuple<string, Action>> steps = new List<Tuple<string, Action>>();
protected void RegisterStep(string parameter, Action someLogic)
{
steps.Add(Tuple.Create(parameter, someLogic));
}
protected void Run()
{
foreach (var step in steps)
{
var result = RunStep(step.Item1);
if (result == null)
{
break;
}
// perform some logic
step.Item2();
}
}
private object RunStep(string parameter)
{
// some implementation
return null;
}
}
class Derived : Base
{
public Derived()
{
RegisterStep("1", () => { });
RegisterStep("2", () => { });
RegisterStep("3", () => { });
// etc
}
}
There's no way to make a function call exit the calling function except for throwing an Exception, which you shouldn't do.
What you can do to make your code cleaner is to invert the cases.
object result = RunStep("mystring1");
if (result == null) return;
result = RunStep("mystring2");
if (result == null) return;
result = RunStep("mystring3");
if (result == null) return;

A way to call method once

I have the following, I want to move the setting of webDB and item outside of the following public string method which is an example how would I go about doing this.
public string Width
{
get
{
if (webDB != null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
Sitecore.Data.Items.Item item = webDB.Items[StartItem];
if (item != null)
{
Sitecore.Data.Fields.Field field = item.Parent.Fields["Identity_Page_Width"];
if (!String.IsNullOrEmpty(field.Value))
{
return field.Value;
}
else
{
return "964"; // returns default pixel width if Identity_Page_Width is not defined, or is null
}
}
else
{
return "964"; // If item is not found return default width.
}
}
else
{
return "964";
}
}
}
This is how I have attempted to separate it:
public void GetConfiguration()
{
if (webDB != null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
if (item != null)
{
item = webDB.Items[StartItem];
}
}
}
but I get stuck with trying to run the method within the code I get method must have a return type.
I then want to run this GetConfiguration only ONCE within the class somewhere so all methods don't need to contact the database and items data more then they have to.
I could do MyClass class = New MyClass; Class.GetConfiguration(); but I don't want future coders to have to know this needs to be instantiated every time to continue. I would rather remove that dependency.
If webDB being instantiated is critical for most/all functionality of the class, consider initializing it in the instance constructor (if non-static), or a static constructor (if static)
Otherwise, I would create a
private InitializeWebDB(){if(webDB == null){...}}
which you can call within your class when needed.
Further, on properties which require access to this, I would use methods instead such as:
public String GetWidth(){InitializeDB(); ...}
which implies more logic/overhead than a simple property field return.
Your code can be improved in a few ways. But to answer your question -
Why not use a static c'tor? This way you ensure it only runs once
public class SomeClass
{
static SomeClass()
{
if (webDB != null)
// etc. etc.
}
... // other code
}
Making the webDB variable static would impose that it will only be null in your first Property call.
private static <whatevertype> webDB;
private static <whatevertype> item;
public void GetConfiguration()
{
if (webDB == null)
{
webDB = Sitecore.Configuration.Factory.GetDatabase("web");
if (item != null)
item = webDB.Items[StartItem];
}
}

Determining if a method calls a method in another assembly containing a new statement and vice-versa

I want to write a rule that will fail if an object allocation is made within any method called by a method marked with a particular attribute.
I've got this working so far, by iterating up all methods calling my method to check using CallGraph.CallersFor(), to see if any of those parent methods have the attribute.
This works for checking parent methods within the same assembly as the method to be checked, however reading online, it appears that at one time CallGraph.CallersFor() did look at all assemblies, however now it does not.
Question: Is there a way of getting a list of methods that call a given method, including those in a different assembly?
Alternative Answer: If the above is not possible, how do i loop through every method that is called by a given method, including those in a different assembly.
Example:
-----In Assembly A
public class ClassA
{
public MethodA()
{
MethodB();
}
public MethodB()
{
object o = new object(); // Allocation i want to break the rule
// Currently my rule walks up the call tree,
// checking for a calling method with the NoAllocationsAllowed attribute.
// Problem is, because of the different assemblies,
// it can't go from ClassA.MethodA to ClassB.MethodB.
}
}
----In Assembly B
public var ClassAInstance = new ClassA();
public class ClassB
{
[NoAllocationsAllowed] // Attribute that kicks off the rule-checking.
public MethodA()
{
MethodB();
}
public MethodB()
{
ClassAInstance.MethodA();
}
}
I don't really mind where the rule reports the error, at this stage getting the error is enough.
I got round this issue by adding all referenced dlls in my FxCop project, and using the code below, which builds a call tree manually (it also adds calls for derived classes to work round another problem i encountered, here.
public class CallGraphBuilder : BinaryReadOnlyVisitor
{
public Dictionary<TypeNode, List<TypeNode>> ChildTypes;
public Dictionary<Method, List<Method>> CallersOfMethod;
private Method _CurrentMethod;
public CallGraphBuilder()
: base()
{
CallersOfMethod = new Dictionary<Method, List<Method>>();
ChildTypes = new Dictionary<TypeNode, List<TypeNode>>();
}
public override void VisitMethod(Method method)
{
_CurrentMethod = method;
base.VisitMethod(method);
}
public void CreateTypesTree(AssemblyNode Assy)
{
foreach (var Type in Assy.Types)
{
if (Type.FullName != "System.Object")
{
TypeNode BaseType = Type.BaseType;
if (BaseType != null && BaseType.FullName != "System.Object")
{
if (!ChildTypes.ContainsKey(BaseType))
ChildTypes.Add(BaseType, new List<TypeNode>());
if (!ChildTypes[BaseType].Contains(Type))
ChildTypes[BaseType].Add(Type);
}
}
}
}
public override void VisitMethodCall(MethodCall call)
{
Method CalledMethod = (call.Callee as MemberBinding).BoundMember as Method;
AddCallerOfMethod(CalledMethod, _CurrentMethod);
Queue<Method> MethodsToCheck = new Queue<Method>();
MethodsToCheck.Enqueue(CalledMethod);
while (MethodsToCheck.Count != 0)
{
Method CurrentMethod = MethodsToCheck.Dequeue();
if (ChildTypes.ContainsKey(CurrentMethod.DeclaringType))
{
foreach (var DerivedType in ChildTypes[CurrentMethod.DeclaringType])
{
var DerivedCalledMethod = DerivedType.Members.OfType<Method>().Where(M => MethodHidesMethod(M, CurrentMethod)).SingleOrDefault();
if (DerivedCalledMethod != null)
{
AddCallerOfMethod(DerivedCalledMethod, CurrentMethod);
MethodsToCheck.Enqueue(DerivedCalledMethod);
}
}
}
}
base.VisitMethodCall(call);
}
private void AddCallerOfMethod(Method CalledMethod, Method CallingMethod)
{
if (!CallersOfMethod.ContainsKey(CalledMethod))
CallersOfMethod.Add(CalledMethod, new List<Method>());
if (!CallersOfMethod[CalledMethod].Contains(CallingMethod))
CallersOfMethod[CalledMethod].Add(CallingMethod);
}
private bool MethodHidesMethod(Method ChildMethod, Method BaseMethod)
{
while (ChildMethod != null)
{
if (ChildMethod == BaseMethod)
return true;
ChildMethod = ChildMethod.OverriddenMethod ?? ChildMethod.HiddenMethod;
}
return false;
}
}
Did you give it a try in this way,
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
object [] items = methodBase.GetCustomAttributes(typeof (NoAllocationsAllowed));
if(items.Length > 0)
//do whatever you want!

Categories

Resources