With the DynamicObject base class you can build a lot of proxy classes that intercept method or property calls to whatever object.
To implement a proxy with DynamicObject the pattern is very simple:
1) Write a class that inherit from DynamicObject and implement a constructor that accepts an instance of the object that you want to incapsulate:
public class Proxy<T> : DynamicObject
{
private T _obj;
public Proxy(T obj)
{
_obj = obj;
}
public T Unwrap()
{
return _obj;
}
public void Wrap(T obj)
{
_obj = obj;
}
}
2) Starting from 1, add overrides to TryInvokeMember to intercept method calls. TrySetMember and TryGetMember to intercept property calls and use reflection to execute member calls on the encapsulated object.
With Entity Framework 4.1 now you have the new DbContext class. With this, is very easy to handle insert, update and delete operation with disconnected entities.
For example: suppose that you want to perform an update operation using an instance of a class named Customer for CustomerId = 3.
Now you can write code like this:
using (var db = new MyDBContextClass())
{
Customer c = new Customer()
{
CustomerId = 3,
LastName = "Vincenzo",
FirstName = "Tenisci"
};
db.Entry(c).State = System.Data.EntityState.Modified;
db.SaveChanges();
}
Very simple! All you have to do is to attach your Customer instance to your DbContext class via the Entry method and put this instance in a Modified state with the System.Data.EntityState enum. After this you call SaveChanges method to perform update.
Armed with this knowledge now we are ready for our DbContext proxy class.
Suppose that you want to write code like this:
using (var db = new EntityDemoDBContext())
{
dynamic proxy = new DbContextProxy(db);
proxy.InsertCustomer(c);
OR
proxy.DeleteCustomer(c);
OR
proxy.UpdateCustomer(c);
}without writing explicitly Insert, Update or Delete methods!
Here is the class:
public class DbContextProxy : DynamicObject
{
DbContext _context;
public DbContextProxy(DbContext context)
{
_context = context;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
string methodName = binder.Name;
result = null;
if (args[0] == null)
return true;
if (methodName.StartsWith("Insert"))
result = InsertMethod(args[0]);
else if (methodName.StartsWith("Delete"))
result = DeleteMethod(args[0]);
else if (methodName.StartsWith("Update"))
result = UpdateMethod(args[0]);
return true;
}
private object UpdateMethod(object entity)
{
_context.Entry(entity).State=System.Data.EntityState.Modified;
return _context.SaveChanges();
}
private object DeleteMethod(object entity)
{
_context.Entry(entity).State = System.Data.EntityState.Deleted;
return _context.SaveChanges();
}
private object InsertMethod(object entity)
{
_context.Entry(entity).State = System.Data.EntityState.Added;
return _context.SaveChanges();
}
}
To use this class (see example above) you have to follow this two rules:
1) Your dynamic method names must start with Insert, Update or Delete prefix.
2) You have to pass an instance of the entity that you want to insert or update or delete.
Hope this helps
Vincenzo
